وبلاگ نت‌آرامآموزش، تجربه و راهکارهای زیرساخت

خطای 203/EXEC در systemd چیست؟ راه‌اندازی سرویس لینوکس قدم‌به‌قدم

آموزش رفع خطای status=203/EXEC در سرور لینوکس، از بررسی مسیر ExecStart و مجوز فایل تا اصلاح اسکریپت و تست سرویس.

انتشار:
توسط تیم فنی نت‌آرام
۷ دقیقه زمان مطالعه
۰ دیدگاه
محتوای تخصصی، ساده و کاربردی
هماهنگ با هویت حرفه‌ای نت‌آرام
بازگشت به لیست مقالات
تصویر شاخص مقاله خطای 203/EXEC در systemd چیست؟ راه‌اندازی سرویس لینوکس قدم‌به‌قدم در وبلاگ نت‌آرام
محتوای آموزشی وبلاگ نت‌آرام
سرویسی برای برنامه خود ساخته‌اید، اما بعد از اجرای آن در وضعیت سرویس عبارت status=203/EXEC دیده می‌شود. معنی ساده این خطا آن است که systemd نتوانسته دستور شروع برنامه را اجرا کند. ممکن است مسیر فایل اشتباه باشد، اجازه اجرا وجود نداشته باشد یا مفسری که اسکریپت به آن نیاز دارد پیدا نشود. خود این عدد نمی‌گوید کدام‌یک از این علت‌ها رخ داده است.
در این راهنما با یک مثال واقعی جلو می‌رویم: سرویسی به نام myapp.service و یک برنامه فرضی در /opt/myapp/. شما باید نام سرویس، کاربر و مسیر را با مقادیر واقعی خودتان جایگزین کنید. دستورها را پس از اتصال SSH یا ورود به کنسول، در ترمینال خود سرور اجرا کنید. مثال برای یک سرویس سیستمی در Ubuntu و AlmaLinux است؛ سرویس‌های کاربری که با systemctl --user اجرا می‌شوند تنظیم و دسترسی متفاوتی دارند.

۱. پیام اصلی را از گزارش پیدا کنید

ابتدا وضعیت سرویس را ببینید:
کد / دستورsudo systemctl status myapp.service --no-pager -l
اگر عبارت status=203/EXEC دیده می‌شود، چند خط اطراف آن را هم بخوانید. عبارتی مانند No such file or directory اغلب به مسیر فایل یا مفسر اشاره می‌کند و Permission denied به دسترسی یا سیاست امنیتی. این‌ها سرنخ‌اند و باید با اطلاعات مراحل بعد تأیید شوند.
برای دیدن گزارش همین سرویس در بوت فعلی:
کد / دستورsudo journalctl -u myapp.service -b --no-pager -n 80
نام فایلی را که پس از Failed at step EXEC spawning آمده یادداشت کنید. گزارش ممکن است اطلاعات محرمانه داشته باشد؛ پیش از ارسال آن به دیگران، رمزها و آدرس‌های خصوصی را حذف کنید. اگر به‌جای 203 پیام start-limit-hit می‌بینید، بعد از رفع علت از راهنمای محدودیت شروع سرویس هم کمک بگیرید.

۲. ببینید systemd دقیقاً چه چیزی را اجرا می‌کند

کد / دستورsudo systemctl cat myapp.service
خط ExecStart مسیر و آرگومان‌های شروع را مشخص می‌کند. این خروجی فایل اصلی و تغییرات اضافی، موسوم به override، را نشان می‌دهد. ممکن است شما فایل اصلی را ویرایش کرده باشید ولی override مسیر دیگری را اعمال کند. این دستور اطلاعات خلاصه بیشتری می‌دهد:
کد / دستورsystemctl show myapp.service -p FragmentPath -p DropInPaths -p User -p Group -p ExecStart
FragmentPath محل فایل اصلی است و DropInPaths فایل‌های تغییرات اضافی را نشان می‌دهد. User مشخص می‌کند سرویس با کدام کاربر اجرا می‌شود؛ خالی بودن آن در سرویس سیستمی معمولاً به معنی اجرای پیش‌فرض با root است. رمزها یا متغیرهای محرمانه را در گزارش منتشر نکنید.

۳. مسیر برنامه را با فایل واقعی مقایسه کنید

فرض کنید در ExecStart مسیر /opt/myapp/run.sh نوشته شده است. وجود آن را بررسی کنید:
کد / دستورls -l /opt/myapp/run.sh
اگر No such file or directory می‌بینید، مسیر در فایل سرویس اشتباه است یا برنامه به محل دیگری منتقل شده است. در پوشه پروژه فایل موجود را پیدا کنید:
کد / دستورls -la /opt/myapp
اگر پوشه دیگری برای استقرار برنامه استفاده می‌کنید، همان پوشه را بنویسید. نام فایل و بزرگی یا کوچکی حروف را دقیق مقایسه کنید. برای برنامه‌های نصب‌شده در مسیر سیستم، محل برنامه را نیز می‌توانید پیدا کنید؛ برای نمونه:
کد / دستورcommand -v python3
خروجی ممکن است /usr/bin/python3 باشد. این مسیر را فقط زمانی در سرویس به کار ببرید که برنامه شما واقعاً با همان نسخه پایتون کار می‌کند؛ برنامه‌ای که در محیط مجازی پایتون نصب شده ممکن است به مفسر داخل venv خودش نیاز داشته باشد.

۴. اجازه اجرای فایل و عبور از پوشه‌ها را بررسی کنید

مسیر باید برای همان کاربری که در User مشخص است قابل دسترسی باشد. فقط وجود فایل کافی نیست؛ دسترسی پوشه‌های بالادستی هم اهمیت دارد:
کد / دستورnamei -l /opt/myapp/run.sh
خروجی هر جزء مسیر، مالک و مجوزها را نمایش می‌دهد. برای دیدن مالک و نوع فایل:
کد / دستورstat -c '%A %U %G %n' /opt/myapp/run.sh
اگر کاربر سرویس مثلاً appuser است، آزمون زیر را با نام واقعی همان کاربر اجرا کنید:
کد / دستورsudo -u appuser test -x /opt/myapp/run.sh && echo 'اجرای فایل مجاز است' || echo 'اجرا برای این کاربر مجاز نیست'
اگر نتیجه دوم را دیدید، ابتدا مالکیت، گروه و مجوز هر پوشه را با مدیر برنامه تطبیق دهید. برای یک اسکریپت متعلق به خودتان، اگر فقط مجوز اجرای مالک جا افتاده و سرویس نیز با همان مالک اجرا می‌شود، می‌توانید از دستور زیر استفاده کنید:
کد / دستورsudo chmod u+x /opt/myapp/run.sh
این دستور فقط اجازه اجرای مالک را اضافه می‌کند. اگر سرویس با کاربر دیگری اجرا می‌شود، همین دستور ممکن است کافی نباشد؛ دسترسی گروه مناسب و پوشه‌ها را مطابق نیاز واقعی تنظیم کنید. استفاده از chmod 777 راه‌حل امنی نیست و مشکل مالکیت را هم توضیح نمی‌دهد.

۵. اگر فایل اسکریپت است، مفسر آن را پیدا کنید

خط اول اسکریپت را ببینید:
کد / دستورhead -n 1 /opt/myapp/run.sh | cat -v
برای یک اسکریپت Bash، خط اول معمولاً شبیه #!/bin/bash است. اگر پس از آن ^M دیدید، فایل احتمالاً با پایان خط ویندوزی ذخیره شده و سیستم ممکن است به‌دنبال مسیر ناموجود /bin/bash همراه با کاراکتر اضافی بگردد. ابتدا از فایل بکاپ بگیرید:
کد / دستورsudo cp -a /opt/myapp/run.sh /opt/myapp/run.sh.before-line-endings
فقط اگر مطمئنید فایل یک اسکریپت متنی متعلق به برنامه شماست، پایان خط‌ها را اصلاح کنید:
کد / دستورsudo sed -i 's/\r$//' /opt/myapp/run.sh
سپس دوباره خط اول را ببینید. این کار را روی فایل اجرایی باینری انجام ندهید. اگر نام مفسر در خط اول به مسیری اشاره می‌کند که وجود ندارد، مسیر درست و نسخه سازگار آن را با برنامه تطبیق دهید؛ صرف ساختن یک لینک تصادفی ممکن است مشکل دیگری ایجاد کند.
در مورد برنامه Python، راه دیگر این است که ExecStart صریحاً مفسر مناسب و بعد مسیر فایل برنامه را اجرا کند؛ نمونه‌ای برای برنامه فرضی:
کد / دستورExecStart=/usr/bin/python3 /opt/myapp/app.py
اگر برنامه در محیط مجازی است، مفسر واقعی آن محیط را جایگزین کنید. مسیر و پارامترهای این نمونه را بدون تطبیق با برنامه خود کپی نکنید.

۶. تنظیم سرویس را اصلاح و آزمون کنید

اگر مسیر ExecStart اشتباه است، به‌جای دستکاری فایل نصب‌شده بسته، می‌توانید یک override بسازید. قبل از تغییر خروجی systemctl cat را نگه دارید و در زمان مناسب این ویرایشگر را باز کنید:
کد / دستورsudo SYSTEMD_EDITOR=nano systemctl edit myapp.service
در بخش مجاز ویرایش، برای نمونه برنامه Python فرضی بالا، این خطوط را قرار دهید:
کد / دستور[Service] ExecStart= ExecStart=/usr/bin/python3 /opt/myapp/app.py
خط خالی ExecStart= مقدار قبلی را پاک می‌کند تا دستور جدید جایگزین آن شود. در nano با Ctrl+O و Enter ذخیره کنید و با Ctrl+X خارج شوید. اگر فایل override از قبل تنظیمات مهمی دارد، آن‌ها را بی‌دلیل پاک نکنید. برای برنامه شما ممکن است مفسر، آرگومان‌ها یا نوع سرویس متفاوت باشد.
تنظیم را بررسی کنید و سپس فهرست سرویس‌ها را دوباره بخوانید:
کد / دستورsudo systemd-analyze verify myapp.service کد / دستورsudo systemctl daemon-reload
اگر verify خطا داد، مسیر و متن اعلام‌شده را اصلاح کنید؛ نبود خروجی نیز تضمین نمی‌کند خود برنامه در زمان اجرا سالم است. حالا شمارنده شکست را پاک و سرویس را شروع کنید:
کد / دستورsudo systemctl reset-failed myapp.service کد / دستورsudo systemctl restart myapp.service
شروع یا ری‌استارت ممکن است برای سرویس در حال استفاده وقفه ایجاد کند. دوباره systemctl status و journalctl مرحله اول را بخوانید. دیدن active (running) برای یک سرویس دائمی نشانه خوبی است؛ سرویس‌های oneshot ممکن است عمداً وضعیت دیگری داشته باشند. علاوه بر وضعیت، قابلیت واقعی برنامه، مثلاً پاسخ یک درخواست مجاز، را امتحان کنید.

اگر هنوز خطا باقی است

اگر مسیر و مجوز درست هستند، محل فایل را از نظر گزینه noexec بررسی کنید:
کد / دستورfindmnt -T /opt/myapp/run.sh -o TARGET,SOURCE,FSTYPE,OPTIONS
وجود noexec می‌تواند اجرای مستقیم فایل را محدود کند. آن را بدون شناخت دلیل امنیتی و تأثیر روی سایر برنامه‌ها تغییر ندهید؛ فایل اجرایی را در محل مناسب و تأییدشده برنامه قرار دهید. در AlmaLinux ممکن است SELinux و در Ubuntu ممکن است AppArmor نیز دسترسی را محدود کند؛ گزارش سیاست امنیتی را با زمان همان خطا تطبیق دهید، به‌جای خاموش‌کردن دائمی حفاظت.
اگر دیگر 203/EXEC نمی‌بینید ولی برنامه با خطای جدید متوقف می‌شود، برنامه واقعاً شروع شده و اکنون باید خطای خودش، مثلاً اتصال دیتابیس یا تنظیم محیط، را جداگانه رفع کنید. تعریف رسمی این وضعیت را می‌توانید در مستندات systemd ببینید.
برای اجرای برنامه با منابع و محیط مستقل، مشخصات سرور مجازی ایران نت‌آرام را با نیاز نرم‌افزار خود مقایسه کنید.
اشتراک‌گذاری:
لینکدینتلگرامایکس

دیدگاه‌ها (۰)

دیدگاه‌های تاییدشده و پاسخ‌های تیم نت‌آرام