ساخت سرویس systemd برای اجرای دائمی برنامه

برای اینکه برنامه بعد از ریبوت و کرش خودکار اجرا شود، آن را به‌صورت سرویس systemd تعریف می‌کنید. این روش سبک‌تر و استانداردتر از pm2 و screen است و لاگ‌ها هم در journald جمع می‌شوند.

Systemdمتوسط8 دقیقه

۱ساخت کاربر مخصوص سرویس

برنامه را با کاربر بدون دسترسی و بدون شل ورود اجرا کنید تا در صورت هک شدن، آسیب محدود بماند.

bash
sudo useradd --system --home /opt/myapp --shell /usr/sbin/nologin myapp
sudo mkdir -p /opt/myapp && sudo chown -R myapp:myapp /opt/myapp

۲نوشتن فایل unit

فایل را در /etc/systemd/system/ بسازید. Restart=always برنامه را بعد از هر توقف دوباره اجرا می‌کند و RestartSec فاصلهٔ آن‌هاست.

ini
sudo nano /etc/systemd/system/myapp.service

[Unit]
Description=My Node.js App
After=network.target

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/opt/myapp/.env
ExecStart=/usr/bin/node server.js
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

# محدودیت‌های امنیتی
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target

اگر برنامه با nvm نصب شده، مسیر کامل node را با which node بدهید؛ systemd محیط شل شما را ندارد.

۳بارگذاری و اجرا

بعد از هر تغییر در فایل unit، daemon-reload را بزنید.

bash
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
systemctl status myapp --no-pager

۴مشاهدهٔ لاگ

خروجی برنامه در journald ذخیره می‌شود؛ نیازی به فایل لاگ جدا نیست.

bash
journalctl -u myapp -f
journalctl -u myapp --since "1 hour ago" --no-pager
journalctl -u myapp -p err -n 50

۵دستورهای روزمره

شروع، توقف و راه‌اندازی مجدد سرویس:

bash
sudo systemctl restart myapp
sudo systemctl stop myapp
sudo systemctl disable myapp
systemctl is-active myapp
systemctl is-enabled myapp

۶بررسی نحو فایل و عیب‌یابی

اگر سرویس بالا نیامد ابتدا نحو فایل را بررسی کنید و بعد لاگ را ببینید. کد خروجی 203/EXEC یعنی مسیر ExecStart درست نیست و 217/USER یعنی کاربر وجود ندارد.

bash
systemd-analyze verify /etc/systemd/system/myapp.service
systemctl status myapp --no-pager -l
journalctl -xeu myapp

۷زمان‌بندی با systemd timer (جایگزین cron)

برای کارهای زمان‌بندی‌شده می‌توانید یک service و timer بسازید. مزیت: لاگ در journald و امکان اجرای جامانده (Persistent).

ini
# /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh

# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup nightly
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target

# فعال‌سازی
sudo systemctl enable --now backup.timer
systemctl list-timers

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

systemd بهتر است یا pm2؟

برای سرور لینوکسی systemd معمولاً کافی و ساده‌تر است: بدون وابستگی اضافه، شروع خودکار در بوت و لاگ مرکزی. pm2 قابلیت‌هایی مثل cluster mode و مانیتورینگ Node دارد که اگر لازم بود می‌توانید از آن استفاده کنید.