نوشتن یک سرویس systemd برای برنامه‌ی خودتان

· ۶ دقیقه مطالعه

لینوکس

زمانی برنامه‌ها را با nohup ./app & اجرا می‌کردم و هر بار که سرور راه‌اندازی دوباره می‌شد، یادم می‌رفت دوباره بالا بیاورمشان. systemd این مشکل را برای همیشه حل می‌کند و نوشتن یک unit ساده کمتر از پنج دقیقه وقت می‌گیرد.

یک unit کامل

# /etc/systemd/system/myapp.service
[Unit]
Description=My application
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/etc/myapp/env
ExecStart=/opt/myapp/bin/server --port 3000
Restart=on-failure
RestartSec=3

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now myapp
systemctl status myapp

enable یعنی بعد از هر بوت اجرا شود و --now یعنی همین حالا هم شروع کند. بعد از هر تغییر در فایل unit باید daemon-reload بزنید، وگرنه systemd همان نسخه‌ی قبلی را در حافظه دارد.

چند نکته که ارزش دانستن دارد

محدود کردن دسترسی

systemd می‌تواند برنامه را در یک محیط محدود اجرا کند. این چند خط را به بخش [Service] اضافه کنید:

NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/myapp

با ProtectSystem=strict کل سیستم‌فایل فقط‌خواندنی می‌شود، مگر مسیرهایی که در ReadWritePaths آورده‌اید. اگر برنامه‌ای نفوذپذیر باشد، مهاجم جای زیادی برای نوشتن ندارد. دستور systemd-analyze security myapp امتیازی از وضعیت فعلی می‌دهد و پیشنهادهای بیشتری هم دارد.

لاگ‌ها

هرچه برنامه روی خروجی استاندارد بنویسد به journal می‌رود:

journalctl -u myapp -f
journalctl -u myapp --since "1 hour ago"