محتوای آموزشی وبلاگ نتآرام
سرویس روی سرور مجازی ایران با ساختن دستی یک پوشه شروع میشود، اما بعد از راهاندازی مجدد دوباره خطای
No such file or directory یا Permission denied میدهد. اگر آن پوشه زیر /run باشد، احتمال دارد برنامه برای socket یا PID به یک مسیر موقتی نیاز داشته و هیچ ابزاری هنگام شروع سرویس آن را دوباره نساخته باشد.در بسیاری از توزیعها
/run حافظه موقت زمان اجرای سیستم است و محتوای آن بعد از ریبوت باقی نمیماند. ساخت یک پوشه دائمی برای داده مهم در آنجا درست نیست. از طرفی هر خطای مجوز هم به این موضوع مربوط نیست. ابتدا مسیر، کاربر و علت واقعی را پیدا میکنیم و فقط برای یک پوشه اختصاصی سرویس، ساخت خودکار را تنظیم میکنیم.۱. خطای همان سرویس را پیدا کنید
با SSH یا کنسول لینوکس وارد شوید و نام نمونه را با سرویس واقعی جایگزین کنید:
کد / دستورsystemctl status myapp.service --no-pager -l
sudo journalctl -u myapp.service -b --no-pager
systemctl cat myapp.service
دستور اول وضعیت، دومی لاگ این سرویس در بوت فعلی و سومی فایل واحد و تنظیمهای تکمیلی را نشان میدهد. دنبال مسیر دقیق و پیام نزدیک زمان توقف بگردید. اگر خطا درباره فایل برنامه، فایل تنظیم یا اتصال شبکه است، ایجاد پوشه runtime مشکل را حل نمیکند. اگر خطا
200/CHDIR و مربوط به پوشه کاری سرویس است، راهنمای WorkingDirectory را دنبال کنید؛ آن مسیر و عمرش ممکن است با پوشه موقت فرق کند.اگر برنامه بعد از ساخت دستی پوشه کار میکند، باز هم نام مسیر و مجوزها را ثبت کنید. ممکن است ساخت دستی موقتاً نشانه را پنهان کند اما بعد از توقف سرویس یا ریبوت مشکل برگردد.
۲. مسیر و هویت سرویس را با هم تطبیق دهید
فرض میکنیم لاگ به
کد / دستور/run/myapp/server.sock اشاره میکند. این مسیر تنها مثال است:systemctl show myapp.service -p User -p Group -p DynamicUser -p RuntimeDirectory -p RuntimeDirectoryMode
ls -ld /run /run/myapp
namei -l /run/myapp/server.sock
اگر
/run/myapp وجود ندارد، دستورهای مسیر ممکن است خطا بدهند و همین اطلاعات مفید است. namei اجزای مسیر و دسترسی آنها را نمایش میدهد. خروجی User و Group حساب تنظیمشده در واحد را نشان میدهد؛ مقدار خالی معمولاً به معنی اجرای system service با پیشفرض root است، اما برنامه ممکن است بعداً خودش سطح دسترسی را تغییر دهد. مستند برنامه و فایل واحد را هم بخوانید. در سرویس دارای DynamicUser یا sandbox، جزئیات دسترسی و مسیر ممکن است متفاوت باشد.اگر پوشه هست ولی برنامه اجازه نوشتن ندارد، مالک و حالت دسترسی آن را با کاربر واقعی برنامه مقایسه کنید. مجوز
777 به همه کاربران دسترسی نوشتن میدهد و درمان مناسب نیست. برای socket مشترک بین دو سرویس ممکن است گروه و مجوز خاص لازم باشد؛ آنها را از تنظیمات برنامه و سیاست امنیتی همان سرور مشخص کنید.۳. مطمئن شوید پوشه واقعاً موقت و اختصاصی است
فایل تنظیم برنامه را بخوانید و ببینید PID، socket یا فایل موقت دقیقاً کجا نوشته میشود. اگر داده پایدار، کلید یا اطلاعات کاربر در مسیر قرار دارد، آن را بهعنوان runtime موقت مدیریت نکنید.
RuntimeDirectory بهطور پیشفرض با توقف سرویس میتواند پوشه تعریفشده را پاک کند و هنگام ایجاد روی پوشه موجود نیز ممکن است مالکیت زیرمجموعه را تغییر دهد. بنابراین آن را روی /run، پوشه مشترک یا مسیر دارای اطلاعات مهم تنظیم نکنید.اگر بسته برنامه خودش واحد یا فایل
tmpfiles.d برای ساخت پوشه دارد، ابتدا علت اجرا نشدن همان تنظیم را پیدا کنید؛ اضافهکردن یک سازوکار رقیب ممکن است مالکیت را بههم بزند. برای تنظیم پیچیده یا پوشه مشترک با عمر مستقل، مدیر سیستم ممکن است tmpfiles.d را انتخاب کند. مستند systemd رفتار ساخت و حذف پوشه را توضیح میدهد.۴. برای یک سرویس ساده، پوشه را به systemd بسپارید
این مثال فقط وقتی مناسب است که برنامه شما از
کد / دستور/run/myapp استفاده میکند، پوشه اختصاصی و موقت است، و User و Group فعلی واحد همان مالک مورد نیاز برنامهاند. پیش از تغییر، خروجی systemctl cat و مقدارهای قبلی را ذخیره کنید. در زمان نگهداری اجرا کنید:sudo systemctl edit myapp.service
در ویرایشگر فایل تکمیلی، این بخش را اضافه و ذخیره کنید:
کد / دستور[Service]
RuntimeDirectory=myapp
RuntimeDirectoryMode=0750
در یک system service، نام نسبی
myapp به /run/myapp اشاره میکند؛ مسیر کامل /run/myapp را به جای نام در این گزینه وارد نکنید. حالت 0750 مثال است: مالک دسترسی کامل، گروه خواندن و عبور و دیگران دسترسی ندارند. اگر کاربر دیگری باید socket را باز کند، گروه و مجوز مناسب برنامه را جدا تعیین کنید. این مثال User را عوض نمیکند؛ اگر واحد root اجرا شود و برنامه بعداً به حساب دیگری تبدیل شود، مالک پیشفرض پوشه ممکن است برای آن مناسب نباشد. در آن حالت از روش توصیهشده خود برنامه یا تنظیم دقیق حساب و گروه با مسئول سرویس استفاده کنید.۵. تغییر را اعمال و از یک نشست جدا تأیید کنید
کد / دستورsudo systemctl daemon-reload
systemctl cat myapp.service
sudo systemctl restart myapp.service
systemctl status myapp.service --no-pager -l
ls -ld /run/myapp
بازراهاندازی سرویس باعث اختلال کوتاه میشود؛ آن را فقط در زمان هماهنگشده انجام دهید. بعد از شروع، پوشه باید با مالک و مجوز مورد انتظار وجود داشته باشد و برنامه باید socket یا PID مورد نیاز را بسازد. با یک درخواست واقعی به سرویس، عملکرد آن را نیز آزمایش کنید. اگر واحد بالا آمد اما برنامه همچنان
Permission denied میدهد، مسیر دقیق، کاربر واقعی، گروه مشتری socket و محدودیتهای SELinux یا AppArmor را طبق لاگ همان سیستم بررسی کنید؛ تغییر تصادفی مجوز تمام مسیرها درست نیست.برای اطمینان از رفتار بعد از بوت، در پنجره مناسب و با دسترسی کنسول، یک بار سرور را بازراهاندازی کنید و همین وضعیت و درخواست واقعی را دوباره بررسی کنید. موفقیت یک بار اجرای دستی برای اثبات ساخت خودکار کافی نیست.
۶. اگر تغییر جواب نداد، چطور برگردیم؟
با
sudo systemctl edit myapp.service همان فایل تکمیلی را به تنظیم قبلی برگردانید؛ به تنظیمهای دیگری که قبلاً در آن فایل بودهاند دست نزنید. پس از ذخیره، sudo systemctl daemon-reload و در زمان مجاز بازراهاندازی سرویس را انجام دهید و وضعیت را با تنظیم ثبتشده قبلی مقایسه کنید. اگر برنامه توسط بسته دیگری پوشه را میسازد، مستند و مالک آن سازوکار را بررسی کنید. اگر مشکل از حساب یا مسیر نادرست است، رفع همان علت لازم است؛ RuntimeDirectory برای همه خطاهای شروع سرویس راهحل عمومی نیست.اشتراکگذاری:
لینکدینتلگرامایکس
مقاله قبلی
مقاله قبلی وجود ندارد.
مقاله بعدی
دیدگاهها (۰)
دیدگاههای تاییدشده و پاسخهای تیم نتآرام
