ساخت سرویس systemd برای اجرای دائمی برنامه
برای اینکه برنامه بعد از ریبوت و کرش خودکار اجرا شود، آن را بهصورت سرویس systemd تعریف میکنید. این روش سبکتر و استانداردتر از pm2 و screen است و لاگها هم در journald جمع میشوند.
۱ساخت کاربر مخصوص سرویس
برنامه را با کاربر بدون دسترسی و بدون شل ورود اجرا کنید تا در صورت هک شدن، آسیب محدود بماند.
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 فاصلهٔ آنهاست.
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 را بزنید.
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
systemctl status myapp --no-pager۴مشاهدهٔ لاگ
خروجی برنامه در journald ذخیره میشود؛ نیازی به فایل لاگ جدا نیست.
journalctl -u myapp -f
journalctl -u myapp --since "1 hour ago" --no-pager
journalctl -u myapp -p err -n 50۵دستورهای روزمره
شروع، توقف و راهاندازی مجدد سرویس:
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 یعنی کاربر وجود ندارد.
systemd-analyze verify /etc/systemd/system/myapp.service
systemctl status myapp --no-pager -l
journalctl -xeu myapp۷زمانبندی با systemd timer (جایگزین cron)
برای کارهای زمانبندیشده میتوانید یک service و timer بسازید. مزیت: لاگ در journald و امکان اجرای جامانده (Persistent).
# /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 دارد که اگر لازم بود میتوانید از آن استفاده کنید.