فایل واحد systemd service با پسوند .service به systemd میگوید یک فرایند را چطور اجرا، نظارت و در صورت نیاز ریاستارت کند. این آموزش از صفر یک unit ساده میسازد؛ گزینههای بخش [Service] و الگوی کلی در صفحهٔ رسمی systemd.service(5) آمده است.
آموزش systemd service در لینوکس؛ ساخت unit از صفر
پیشنیازهایی که مبتدی جا میاندازد: دسترسی sudo روی اوبونتو/دبیان یا توزیع مشابه، مسیری مطلق به باینری یا اسکریپت (نه تکیه به PATH مبهم در سرویس)، دانستن اینکه سرویس با کدام کاربر باید اجرا شود، و جدا کردن میزبان لینوکس از فرایند برنامه. unit را اول در /etc/systemd/system/ میگذارید؛ بعد daemon-reload و enable/start.
- یک پوشه یا اسکریپت آزمایشی آماده کنید که در شِل دستی بدون خطا اجرا میشود؛ مثلاً یک باینری یا /usr/local/bin/myapp.
- با ویرایشگر فایل واحد بسازید: sudo nano /etc/systemd/system/myapp.service.
- بخش [Unit] را با Description= و در صورت نیاز After=network.target پر کنید؛ اینها گزینههای مشترک واحدند.
- بخش [Service] را طبق man page بسازید: حداقل Type=simple (پیشفرض رایج)، ExecStart=/usr/local/bin/myapp با مسیر مطلق، و ترجیحاً User= و Group= غیر root وقتی ممکن است.
- بخش [Install] را با WantedBy=multi-user.target بگذارید تا enable معنی داشته باشد.
- ذخیره کنید؛ سپس sudo systemctl daemon-reload را بزنید تا واحد جدید دیده شود.
- sudo systemctl start myapp.service و بعد sudo systemctl status myapp.service را بزنید؛ برای شروع خودکار بعد از بوت: sudo systemctl enable myapp.service.
- لاگ را با journalctl -u myapp.service -e بخوانید؛ اگر ExecStart خطا بدهد معمولاً مسیر، مجوز یا وابستگی شبکه است.
طبق systemd.service(5)، گزینههای مخصوص سرویس در [Service] هستند و محیط اجرا در صفحات مرتبط مثل systemd.exec هم تعریف میشود. برای برنامهٔ foreground معمولاً Type=simple کافی است؛ اگر خود برنامه fork میکند باید Type را با رفتار واقعیاش هماهنگ کنید، نه از روی عادت.
اگر سرویس بلافاصله failed میشود، خروجی systemctl status و چند خط آخر journalctl -u را (بدون رمز) در نظرات بگذارید تا خطای ExecStart را جدا کنیم.
خطاهای رایج و امنیت
- Unit not found بعد از ساخت فایل → daemon-reload را فراموش کردهاید یا نام فایل با نام واحد یکی نیست.
- status=203/EXEC → مسیر ExecStart غلط است یا فایل اجرایی نیست.
- با root کار میکند با User نه → مجوز فایل، پوشهٔ داده یا پورت محدود.
- بعد از بوت بالا نمیآید → enable نشده یا After/Wants شبکه ناقص است.
- سرویس شبکهای را بیدلیل با User=root و بدون محدودیت اجرا نکنید؛ حداقل کاربر جدا و مسیرهای مشخص بگذارید.
اولین سرویس شما یک اسکریپت پایتون است، یک باینری Go، یا پروکسی داخلی؟ Type و User انتخابیتان را هم بنویسید.
Unit خوب اول ساده است: یک ExecStart مشخص، یک User مشخص، یک Restart محتاط. پیچیدگیهایی مثل socket activation یا template واحدها را بگذارید برای وقتی سرویس ساده پایدار شد. man صفحهٔ systemd.service دقیقاً برای همین گزینههای [Service] نوشته شده است.
تفاوت Type را جدی بگیرید. Type=simple فرض میکند فرایند ExecStart همان سرویس اصلی است و fork نمیکند. اگر برنامه خود را daemon میکند و PID عوض میشود، ممکن است systemd وضعیت را غلط بفهمد. قبل از حدس، رفتار واقعی باینری را در پیشزمینه ببینید.
برای عیبیابی، journalctl -u دقیقتر از خواندن فایل لاگ پراکنده است چون stdout/stderr سرویس را هم جمع میکند. اگر سرویس در حلقهٔ Restart گیر کرده، اول Restart را موقتاً no کنید تا علت خروج را در status ببینید.
مرجع این آموزش صفحهٔ systemd.service(5) است؛ گزینههای مشترک [Unit]/[Install] را در systemd.unit و محیط اجرا را در systemd.exec دنبال کنید وقتی سرویس از حالت آزمایشی خارج شد.