## 服务文件长什么样
systemd的服务文件放在`/etc/systemd/system/`下,后缀`.service`。写一个最简单的:
[Unit]
Description=My Python App
After=network.target
[Service]
ExecStart=/usr/bin/python3 /opt/app/main.py
Restart=always
User=appuser
[Install]
WantedBy=multi-user.target
`ExecStart`是启动命令,路径必须写绝对路径。`Restart=always`表示挂了自动重启,生产环境基本必加。`User`指定运行用户,别用root跑服务。
## 核心操作命令
# 立即启动
systemctl start myapp.service
# 设置开机自启
systemctl enable myapp.service
# 查看状态(最常用)
systemctl status myapp.service
# 查看日志
journalctl -u myapp.service
`status`会显示当前状态、最近日志、PID。排查问题第一件事就是跑这个。
## 日志查看技巧
# 只看最近50行
journalctl -u myapp.service -n 50
# 实时跟踪
journalctl -u myapp.service -f
# 只看今天的
journalctl -u myapp.service --since today
# 按时间范围
journalctl -u myapp.service --since "2024-01-01 10:00" --until "2024-01-01 12:00"
`-f`类似`tail -f`,调试时开一个窗口挂着很爽。
## 环境变量和参数
[Service]
Environment=DB_HOST=127.0.0.1
Environment=DB_PORT=3306
EnvironmentFile=/etc/myapp/env.conf
ExecStart=/usr/bin/python3 /opt/app/main.py --port 8080
多个变量用多个`Environment`行,或者用`EnvironmentFile`加载整个文件。文件每行格式`KEY=VALUE`。
## 依赖和启动顺序
[Unit]
Description=Web App
After=network.target mysql.service redis.service
Requires=mysql.service redis.service
`After`只控制顺序,不保证依赖启动。`Requires`表示如果依赖挂了,这个服务也会停。常用组合是`After`+`Requires`。
## 重载配置
改了service文件后必须重载:
systemctl daemon-reload
systemctl restart myapp.service
不重载直接restart,systemd用的还是旧配置。踩过这个坑的人不少。
## 定时任务(Timer)
不用cron,systemd自带timer:
写一个timer文件`/etc/systemd/system/backup.timer`:
[Unit]
Description=Daily backup
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
对应的service文件`backup.service`:
[Unit]
Description=Backup script
[Service]
ExecStart=/usr/local/bin/backup.sh
Type=oneshot
启用:
systemctl enable backup.timer
systemctl start backup.timer
`OnCalendar=daily`每天0点跑。`Persistent=true`表示如果错过了(比如关机),开机后补跑。
## 常见坑
Type设置不对:默认`simple`,如果进程fork了子进程,用`forking`,否则systemd认为进程已退出。拿不准用`exec`,它等待主进程真正退出。
ExecStop没写:默认发SIGTERM,有些程序不吃,需要自定义:
ExecStop=/bin/kill -SIGTERM $MAINPID
ExecStopPost=/bin/rm -f /var/run/myapp.pid
启动超时:默认90秒,启动慢的加:
TimeoutStartSec=300
TimeoutStopSec=30
## 实战:部署一个Node.js应用到雨云
雨云的服务器性价比不错,稳定好用。部署流程:
1. SSH连上雨云服务器
2. 安装Node.js
3. 写service文件:
[Unit]
Description=Node App
After=network.target
[Service]
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/node /opt/myapp/server.js
Restart=always
RestartSec=10
User=nodeuser
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
4. 上传代码到`/opt/myapp`
5. 创建用户:`useradd -r -s /bin/false nodeuser`
6. 改权限:`chown -R nodeuser:nodeuser /opt/myapp`
7. 启动:`systemctl daemon-reload && systemctl enable –now myapp`
`RestartSec=10`表示挂了等10秒再重启,防止频繁重启打满日志。
## 调试三板斧
服务起不来时:
# 检查语法
systemd-analyze verify /etc/systemd/system/myapp.service
# 查看详细错误
journalctl -xe
# 手动跑命令看报错
sudo -u appuser /usr/bin/python3 /opt/app/main.py
`journalctl -xe`会显示最近一次错误,基本能定位90%的问题。手动跑命令能排除systemd本身的问题。
雨云是国内一家老牌云服务商,提供高性价比的云服务器和虚拟主机。我用它部署了好几个项目,速度和稳定性都不错。通过 https://www.rainyun.com/SAJA_ 注册可以领一张 5折优惠券,有需要的朋友可以看看。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END



暂无评论内容