کران Nextcloud در Docker: چرا جابهای پسزمینه اجرا نمیشوند
هشدار «Last background job execution ran...» در Nextcloud Docker اغلب از اجرا نشدن cron.php داخل کانتینر است. مسیر، کاربر و حالت cron را درست میکنیم.

اگر Nextcloud را در Docker بالا آوردهاید و در صفحه Overview پنل ادمین این هشدار را میبینید: «Last background job execution ran 4 hours ago. Something seems wrong.» احتمالاً تا حالا چند بار crontab هاست را چک کردهاید و خط کران هم سر جایش هست. اما مشکل معمولاً از نبودن کران نیست؛ از این است که آن خط، cron.php را در جای اشتباهی اجرا میکند.
Nextcloud برای کارهایی مثل پاکسازی Trash، حذف نسخههای قدیمی فایلها، تولید preview، پردازش اشتراکهای فدرال و بسیاری کارهای پسزمینه به یک کران واقعی نیاز دارد که هر ۵ دقیقه اجرا شود. اگر این کران درست تنظیم نشود، خود Nextcloud بالا میآید و کاربران میتوانند فایل آپلود کنند، ولی پشت صحنه کمکم به مشکل میخورد.
نشانهها؛ چه چیزی واقعاً دیده میشود
- در پنل ادمین، هشدار «Last background job execution ran ... Something seems wrong» دیده میشود.
- پیشنمایش تصاویر و فایلهای PDF دیر ساخته میشوند یا اصلاً ساخته نمیشوند.
- فایلهای حذفشده مدت زیادی در Trash میمانند و سیاست نگهداری اعمال نمیشود.
- در محیطهای شلوغ، صف کارهای پسزمینه طولانی میشود و
occ background-job:listجابهایی با زمان اجرای گذشته نشان میدهد.
اگر همان دستوری را که در crontab گذاشتهاید، دستی روی هاست اجرا کنید، ممکن است خروجی زیر را ببینید:
Could not open input file: /var/www/html/cron.php
این خطا کل ماجرا را لو میدهد. مسیر /var/www/html/cron.php داخل کانتینر Nextcloud وجود دارد، نه روی فایلسیستم هاست. اگر خروجی کران را با >/dev/null 2>&1 خاموش کرده باشید، این خطا هیچجا ثبت نمیشود و فقط هشدار ادمین باقی میماند.
علت ریشهای
سه لایه باعث این رفتار میشود:
- مرز کانتینر: کران روی هاست اجرا میشود، ولی فایل
cron.phpداخل ایمیج Nextcloud است. دستورphp /var/www/html/cron.phpروی هاست به فایلی اشاره میکند که وجود ندارد. باید ازdocker execاستفاده کنید تا دستور داخل کانتینر اجرا شود. - کاربر اشتباه: حتی وقتی از
docker execاستفاده میکنید، اگر-u www-dataرا نزنید، کران با کاربر root داخل کانتینر اجرا میشود. Nextcloud فایلهایی مثل لاگها، previewها و appdata را با مالک root میسازد و بعداً کاربر وب (www-data) نمیتواند آنها را بنویسد. این وضعیت میتواند به خطاهای آپلود و «Cannot write to appdata» منجر شود. - حالت AJAX یا webcron: Nextcloud چند حالت برای background job دارد. در حالت
ajax، جابها فقط وقتی اجرا میشوند که کاربر صفحهای باز کند. روی سروری که کمترافیک است یا بیشتر با API و WebDAV کار میکند، این حالت قابل اتکا نیست. حالتwebcronهم به یک سرویس بیرونی نیاز دارد که مرتب/cron.phpرا صدا بزند و در عمل کمتر درست پیکربندی میشود.
راهحل گامبهگام
۱. نام کانتینر و حالت فعلی را ببینید
در دستورهای این مقاله نام کانتینر را nextcloud گذاشتهام. اگر نام دیگری دارید، همان را جایگزین کنید. اول ببینید کانتینر در حال اجراست و بعد حالت background job را بخوانید:
docker ps
docker exec -u www-data nextcloud php occ config:app:get core backgroundjobs_mode
اگر خروجی ajax یا webcron بود، همان مشکل اصلی است. اگر cron بود، یعنی حالت درست است ولی کران اجرا نمیشود یا خطا میدهد.
۲. حالت را روی cron بگذارید
docker exec -u www-data nextcloud php occ background:cron
بعد از اجرا دوباره دستور occ config:app:get core backgroundjobs_mode را بزنید و مطمئن شوید خروجی cron است. این تغییر فقط حالت را تنظیم میکند؛ هنوز باید کران واقعی روی هاست یا داخل کانتینر اجرا شود.
۳. قبل از تنظیم کران، دستی تست کنید
این مرحله مهم است. اگر دستور زیر بدون خروجی و با کد ۰ تمام شود، یعنی مسیر، کاربر و دسترسیها درست است:
docker exec -u www-data nextcloud php -f /var/www/html/cron.php
echo $?
اگر خطای Could not open input file گرفتید، نام کانتینر یا مسیر فایل اشتباه است. اگر خطای Permission denied گرفتید، کاربر اجرا یا مالکیت فایلها مشکل دارد. اگر قبلاً کران را با root اجرا کردهاید، مالکیت data directory را برگردانید؛ مسیر را با مسیر واقعی data خودتان عوض کنید:
docker exec -u root nextcloud chown -R www-data:www-data /var/www/html/data
۴. خط کران را روی هاست اضافه کنید
با کاربر root وارد crontab شوید:
sudo crontab -u root -e
این خط را اضافه کنید:
*/5 * * * * /usr/bin/docker exec -u www-data nextcloud php -f /var/www/html/cron.php >>/var/log/nextcloud-cron.log 2>&1
چند نکته:
- مسیر
/usr/bin/dockerرا با خروجیcommand -v dockerروی هاست خودتان تطبیق دهید. - نام
nextcloudرا با نام واقعی کانتینر عوض کنید. - در کران از
-itاستفاده نکنید؛ کران TTY ندارد وdocker exec -itممکن است با خطای «the input device is not a TTY» شکست بخورد. - خروجی را به
/dev/nullنفرستید. همین کار باعث میشود خطاهایی مثل نبودن فایل یا Permission denied ماهها مخفی بمانند.
اگر از Docker Compose استفاده میکنید، خط کران میتواند این شکل باشد. توجه کنید که -T برای غیرفعال کردن TTY لازم است و نام سرویس app را با نام سرویس خودتان عوض کنید:
*/5 * * * * cd /opt/nextcloud && /usr/bin/docker compose exec -T -u www-data app php -f /var/www/html/cron.php >>/var/log/nextcloud-cron.log 2>&1
۵. لاگ را بررسی کنید
بعد از چند دقیقه لاگ را ببینید:
sudo tail -n 20 /var/log/nextcloud-cron.log
اگر هیچ خطایی نبینید، خوب است؛ cron.php در حالت موفق معمولاً خروجی تولید نمیکند. اگر خطای Could not open input file یا Permission denied دیدید، به مرحله قبل برگردید. برای اطمینان بیشتر، همان دستور داخل کران را یک بار دستی در shell اجرا کنید و کد خروج را ببینید.
چطور مطمئن شویم مشکل واقعاً حل شده است
- دستور دستی
docker exec -u www-data nextcloud php -f /var/www/html/cron.phpبا کد خروج ۰ تمام میشود. - خروجی
occ config:app:get core backgroundjobs_modeبرابرcronاست. - پس از ۵ تا ۱۰ دقیقه، هشدار «Last background job execution ran ...» در پنل ادمین پاک میشود یا زمان آن بهروز میشود.
- در خروجی
docker exec -u www-data nextcloud php occ background-job:list، ستون آخرین اجرا (last run) برای جابهای دورهای بهروز شده است و جابها با next run در گذشته انبار نمیشوند. - لاگ
/var/log/nextcloud-cron.logبعد از چند چرخه خطای جدیدی ندارد.
اگر هشدار باقی ماند، اول مطمئن شوید کران روی هاست واقعاً اجرا میشود. با crontab -l -u root خط را ببینید و یک بار همان دستور را بدون redirect اجرا کنید. سپس بررسی کنید کانتینر با همین نام در حال اجراست و بعد از ریاستارتها نامش عوض نشده است.
پیشگیری و بهترین روشها
- در محیط production همیشه حالت background job را
cronبگذارید. AJAX برای نصبهای کوچک و کمترافیک است و برای سرور واقعی قابل اتکا نیست. - کران Nextcloud را با کاربر
www-dataاجرا کنید، نه root. این کار از مالکیت نادرست فایلها و خطاهای بعدی جلوگیری میکند. - خروجی کران را ذخیره کنید. اگر نمیخواهید لاگ دائمی داشته باشید، حداقل از
loggerاستفاده کنید تا خطا در syslog دیده شود. - از نام ثابت کانتینر یا نام سرویس Compose استفاده کنید. اگر کانتینر را با نام تصادفی بالا میآورید، کران بعد از هر بازسازی میشکند.
- بعد از هر آپدیت Nextcloud یا تغییر ایمیج، اجرای دستی
cron.phpو وضعیت هشدار ادمین را دوباره چک کنید. - برای لاگ کران logrotate تنظیم کنید تا فایل لاگ در بلندمدت دیسک را پر نکند.
- در Kubernetes بهجای کران هاست، یک CronJob با ایمیج Nextcloud و همان volume داده بسازید و دستور
php -f /var/www/html/cron.phpرا با کاربرwww-dataاجرا کنید.
جمعبندی ساده است: Nextcloud در Docker به کرانی نیاز دارد که داخل همان کانتینر و با همان کاربر وب اجرا شود. اگر خط کران را از روی مستندات کپی کردهاید ولی مسیر را روی هاست اجرا میکنید، فقط هشدار ادمین را جا گذاشتهاید. با یک docker exec -u www-data و ثبت خروجی، هم مشکل را پیدا میکنید و هم از تکرارش جلوگیری میکنید.
نویسنده
تیم محتوای کلودیکپ
تیم فنی و محتوای کلودیکپ؛ مهندسانی که هر روز با DevOps، Kubernetes و زیرساخت ابری کار میکنند و تجربههایشان را اینجا مینویسند.
سوالات متداول این مقاله
نه. اجرای cron.php با root باعث میشود فایلهای appdata، لاگها و previewها با مالک root ساخته شوند و بعداً www-data نتواند آنها را بنویسد. همیشه از -u www-data استفاده کنید.
معمولاً خروجی کران را به /dev/null فرستادهاید و خطایی مثل Could not open input file یا Permission denied دیده نمیشود. نام کانتینر، مسیر cron.php، کاربر اجرا و حالت background:cron را دوباره بررسی کنید.
برای نصبهای کوچک و کمترافیک ممکن است کار کند، ولی قابل اتکا نیست. جابهای پسزمینه فقط با باز شدن صفحه اجرا میشوند و روی سرورهای production یا محیطهایی که بیشتر با API کار میکنند، صف جابها عقب میافتد.
کلودیکپ در این زمینه چه کمکی میکند؟
راهاندازی فضای ابری اختصاصی سازمان با Nextcloud (Self-Hosted)
همه فایلها و اسناد سازمان در فضای ابری اختصاصی خودتان؛ کاملاً امن، با پشتیبانگیری خودکار و قابل دسترس در هر زمان و از هر دستگاه. جایگزین داخلی Google Drive و Dropbox، پایدار حتی در شرایط اینترنت ملی.
مشاهده جزئیات خدمتخدمات مدیریتشده DevOps
برونسپاری کامل عملیات زیرساخت به تیمی متخصص، با پشتیبانی مستمر.
مشاهده جزئیات خدمتبهینهسازی عملکرد و هزینه
شناسایی گلوگاههای عملکردی و منابع بلااستفاده برای کاهش هزینه و افزایش سرعت.
مشاهده جزئیات خدمت
ایمیل تحویل داده میشود ولی Inbox خالی است؛ تلهی mail_location
ایمیل در لاگ Postfix «تحویل داده» میشود اما کاربر هنگام اتصال IMAP صندوق خالی میبیند. علت رایج، اختلاف مسیر تحویل میان Postfix و mail_location در Dovecot است.

رفع خطای no SASL authentication mechanisms در Postfix
وقتی smtpd پورت ۵۸۷ با خطای «no SASL authentication mechanisms» بالا نمیآید، ریشه معمولاً سوکت Dovecot است که داخل chroot پستفیکس ساخته نشده. این مقاله علت و راهحل کامل را قدمبهقدم بررسی میکند.

رفع dkim=none در Postfix با راهاندازی OpenDKIM
اگر ایمیلهای سرور Postfix شما در Gmail به اسپم میروند و هدر پیام dkim=none نشان میدهد، یعنی هیچ امضای DKIM روی پیامها درج نمیشود. در این مقاله OpenDKIM را نصب، پیکربندی و به Postfix وصل میکنیم و رکورد DNS را منتشر میکنیم.
در پیادهسازی به کمک نیاز دارید؟
تیم کلودیکپ همین کار را هر روز برای تیمهای دیگر انجام میدهد. اگر جایی گیر کردهاید، با ما صحبت کنید.