后台运行日志收集进程需解决生命周期管理、输出重定向和启停可控性三问题:nohup+&适用于轻量场景;systemd服务适合生产部署,支持自动重启与日志整合;须配置日志轮转防磁盘满;PID文件+优雅退出保障安全停止。

让进程在后台运行并持续收集日志,关键不是简单加 &,而是要解决进程生命周期管理、输出重定向、启动/停止可控性这三件事。
用 nohup + & 组合实现基础后台驻留
nohup 能屏蔽 SIGHUP 信号,避免终端关闭导致进程退出;& 让命令异步执行。二者配合是轻量级后台运行的常用方式。
- 基本写法:
nohup ./myapp > app.log 2>&1 &—— 标准输出和错误都重定向到app.log,2>&1必须写在重定向文件之后 - 执行后会提示类似
nohup: ignoring input and appending output to 'nohup.out',说明已生效;可用jobs或ps aux | grep myapp确认进程存在 - 注意:该方式启动的进程没有 PID 文件,重启或清理时需手动查杀,不适合生产环境长期托管
用 systemd 管理服务(推荐用于长期运行)
把脚本注册为系统服务,能自动重启、依赖管理、日志整合(journalctl)、开机自启,适合正式部署。
- 新建单元文件,例如
/etc/systemd/system/myapp.service:
[Unit] Description=My Application After=network.target [Service] Type=simple User=myuser WorkingDirectory=/opt/myapp ExecStart=/opt/myapp/run.sh Restart=always RestartSec=10 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
- 启用服务:
sudo systemctl daemon-reload && sudo systemctl enable myapp && sudo systemctl start myapp - 查看日志:
journalctl -u myapp -f(实时)、journalctl -u myapp --since "1 hour ago"(按时间查) - 日志默认由 journald 管理,也可配置
syslog或额外重定向到文件(通过ExecStart中的> /var/log/myapp.log 2>&1)
日志轮转与容量控制(避免磁盘打满)
长期运行的服务必须限制单个日志大小,否则可能撑爆磁盘。systemd 自带日志轮转,Shell 脚本则需手动处理。
- systemd 控制方式(全局或服务级):
编辑/etc/systemd/journald.conf,设置:SystemMaxUse=500MRuntimeMaxUse=200MMaxRetentionSec=2week
修改后执行sudo systemctl restart systemd-journald - 纯 Shell 场景(如用
nohup)可借助logrotate:
新建/etc/logrotate.d/myapp:
/var/log/myapp.log {
daily
missingok
rotate 7
compress
delaycompress
notifempty
create 0644 myuser myuser
sharedscripts
postrotate
kill -USR1 $(cat /var/run/myapp.pid 2>/dev/null) 2>/dev/null || true
endscript
}
- 需确保应用支持 USR1 信号触发日志 reopen(如 nginx),否则仅靠 logrotate 切割会导致新日志仍写入旧文件句柄,需配合
copytruncate选项
安全停止与 PID 可控性
后台进程不能只靠 killall 或模糊匹配,应有明确 PID 记录和优雅退出机制。
- 启动时记录 PID:
./myapp > app.log 2>&1 & echo $! > /var/run/myapp.pid
注意:需确保目录可写,且脚本退出前清理 PID 文件(或用 trap 捕获信号) - 停止脚本示例(
stop.sh):
#!/bin/bash
PID_FILE="/var/run/myapp.pid"
if [[ -f "$PID_FILE" ]]; then
PID=$(cat "$PID_FILE")
if kill -0 "$PID" 2>/dev/null; then
kill "$PID" && rm -f "$PID_FILE"
echo "Stopped process $PID"
else
echo "Process not running, cleaning up stale PID file"
rm -f "$PID_FILE"
fi
else
echo "No PID file found"
fi
- 更稳妥的做法是让应用自身监听信号(如 SIGTERM),完成清理后再退出,避免数据丢失或状态不一致


















