本文目录导读:

- 使用 & 符号(最简单方式)
- 使用 nohup 命令(推荐)
- 使用 disown 命令
- 使用 setsid 命令
- 脚本内部实现后台运行
- 使用 screen 或 tmux(最稳定)
- 使用 systemd 服务(生产环境推荐)
- 综合示例 - 完整的后台脚本模板
- 重要注意事项
- 最佳实践建议
在Shell脚本中实现后台运行,主要有以下几种方法:
使用 & 符号(最简单方式)
在命令末尾添加 & 符号:
# 基本用法 ./my_script.sh & # 带输出的例子 python long_task.py & # 后台运行并保存输出 nohup python long_task.py > output.log 2>&1 &
使用 nohup 命令(推荐)
nohup 可以防止进程在终端关闭时被终止:
# 基本用法 nohup ./my_script.sh & # 指定输出文件 nohup ./my_script.sh > output.log & # 同时重定向错误输出 nohup ./my_script.sh > output.log 2>&1 & # 不保留任何输出 nohup ./my_script.sh > /dev/null 2>&1 &
使用 disown 命令
先后台运行,然后使用 disown 将其从shell作业列表中移除:
# 开始运行 ./my_script.sh & # 查看后台作业 jobs # 将任务从shell中分离 disown %1 # %1 表示第一个后台作业 # 或者立即分离 ./my_script.sh & disown
使用 setsid 命令
创建新的会话来运行进程:
setsid ./my_script.sh & # 或者 setsid ./my_script.sh > output.log 2>&1 &
脚本内部实现后台运行
在脚本内部实现后台运行:
#!/bin/bash
# 后台运行某个函数
run_background_task() {
while true; do
echo "Running background task..."
sleep 10
done
}
# 后台执行
run_background_task &
PID=$!
echo "Background task PID: $PID"
# 继续执行其他任务
echo "Main script continues..."
使用 screen 或 tmux(最稳定)
使用 screen:
# 创建新会话 screen -S my_session # 运行脚本 ./my_script.sh # 分离会话(Ctrl+A 然后按 D) # 重新连接 screen -r my_session
使用 tmux:
# 创建新会话 tmux new -s my_session # 运行脚本 ./my_script.sh # 分离(Ctrl+B 然后按 D) # 重新连接 tmux attach -t my_session
使用 systemd 服务(生产环境推荐)
创建服务文件 /etc/systemd/system/myapp.service:
[Unit] Description=My Application After=network.target [Service] Type=simple User=youruser WorkingDirectory=/path/to/app ExecStart=/path/to/app/my_script.sh Restart=always RestartSec=10 [Install] WantedBy=multi-user.target
# 启动服务 sudo systemctl start myapp # 开机自启 sudo systemctl enable myapp # 查看状态 sudo systemctl status myapp
综合示例 - 完整的后台脚本模板
#!/bin/bash
# 后台运行脚本模板
LOG_FILE="/var/log/myapp.log"
PID_FILE="/var/run/myapp.pid"
start_app() {
# 检查是否已在运行
if [ -f "$PID_FILE" ]; then
echo "App is already running (PID: $(cat $PID_FILE))"
exit 1
fi
# 后台运行并保存PID
nohup /path/to/your/command > "$LOG_FILE" 2>&1 &
PID=$!
echo $PID > "$PID_FILE"
echo "App started with PID: $PID"
}
stop_app() {
if [ -f "$PID_FILE" ]; then
kill $(cat "$PID_FILE")
rm "$PID_FILE"
echo "App stopped"
else
echo "App is not running"
fi
}
status_app() {
if [ -f "$PID_FILE" ] && kill -0 $(cat "$PID_FILE") 2>/dev/null; then
echo "App is running (PID: $(cat $PID_FILE))"
else
echo "App is not running"
fi
}
case "$1" in
start)
start_app
;;
stop)
stop_app
;;
restart)
stop_app
start_app
;;
status)
status_app
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;
esac
重要注意事项
- 输出重定向:后台运行时记得重定向输出,避免占用终端
- 错误处理:使用
2>&1同时重定向错误输出 - PID管理:保存PID以便后续管理和停止
- 资源监控:留意后台进程的资源占用
- 日志轮转:使用
logrotate管理日志文件大小
最佳实践建议
- 开发环境:使用
nohup+& - 生产环境:使用
systemd服务 - 长时间运行:使用
screen或tmux - 需要监控:配合
supervisor或pm2使用
选择哪种方法取决于你的具体需求和使用场景。