shell常驻服务需用while true加sleep控频,推荐sleep 1~2;用trap捕获sigint/sigterm实现优雅退出;通过pid文件防重启;以nohup+日志重定向确保后台稳定运行。

Shell脚本实现常驻后台服务监听,核心在于用可控的死循环配合合理延时,避免空转耗资源,同时保证响应及时性。
用 while true 配合 sleep 控制循环节奏
直接写 while true; do ...; done 会形成 CPU 占用 100% 的忙等待。必须加入 sleep 降低轮询频率。延时时间需权衡:太短(如 sleep 0.1)仍可能抢资源;太长(如 sleep 10)会导致事件响应滞后。
- 常规服务监听推荐
sleep 1或sleep 2,兼顾实时性与负载 - 若监听文件变化或网络端口,可先用轻量命令快速探测(如
nc -z localhost 8080),失败时适当延长休眠(如指数退避) - 避免在循环内执行耗时操作(如大文件读取、复杂计算),否则 sleep 失去调节意义
用 trap 捕获信号实现优雅退出
常驻脚本需支持手动终止(如 kill %1 或 kill $(cat /var/run/myservice.pid))。仅靠 Ctrl+C 不适用于后台进程,必须用 trap 处理 SIGTERM 和 SIGINT。
- 在脚本开头定义清理函数,例如
cleanup() { rm -f /var/run/myservice.pid; exit 0; } - 紧接着注册 trap:
trap cleanup SIGINT SIGTERM - 启动时记录 PID:
echo $$ > /var/run/myservice.pid,确保外部可定位和终止进程
防止重复启动:加锁与 PID 文件校验
同一脚本多次运行易引发冲突(如双写日志、重复绑定端口)。启动前应检查 PID 文件是否存在,并验证对应进程是否存活。
- 读取已有 PID:
pid=$(cat /var/run/myservice.pid 2>/dev/null) - 用
kill -0 $pid 2>/dev/null测试进程是否仍在运行(不发信号,只查权限与存在性) - 若进程存活,直接退出并提示“already running”;否则覆盖写入新 PID
后台运行与日志分离:nohup + 重定向
让脚本真正脱离终端、持续运行,需组合使用 nohup、输出重定向和 &。
- 启动命令示例:
nohup ./watcher.sh > /var/log/watcher.log 2>&1 -
nohup忽略挂断信号,切断 stdin 防止阻塞,<code>> ... 2>&1合并标准输出与错误到日志 - 建议在脚本内部也加简单日志输出,例如
echo "$(date): checking service..." >> /var/log/watcher.log
不复杂但容易忽略。关键不是“能不能跑”,而是“跑得稳、停得准、查得清”。











