重启后后台Cronjobs变为僵尸进程的原因及解决方法
问题:Cron@reboot启动的脚本全部变为僵尸进程的原因与解决方法
问题描述
我设置了60个系统重启后运行的Cron任务,命令如下:
@reboot sleep 900 && /home/creta/Scripts/N1/./N1_Docs.sh > /dev/null 2> /home/creta/Scripts/N1/N1_Docs.log &
脚本内容为:
#!/bin/bash -xv while true; do for z in "/D1/N1/*.pdf"; do /usr/bin/rclone move /D1/N1/ New:D1/N1/ --log-file=/home/user/Scripts/N1/N1_Docs.log done sleep 18 done
脚本功能正常,但全部变成了僵尸进程,请问原因和解决方法?
原因分析
僵尸进程(Z状态)的本质是子进程退出后,父进程未调用wait()/waitpid()系统调用回收其资源。结合你的场景,核心触发点有两个:
- Cron启动的父Shell管控异常:你在Cron命令里额外加了
&,导致脚本的父进程是Cron临时启动的Shell。当Shell完成启动操作后退出,若Cron未及时回收该Shell进程资源,会残留僵尸;更常见的是脚本成为孤儿进程后被init/systemd收养,若脚本意外退出但init未及时清理,也会产生僵尸。 - 脚本子进程回收异常:脚本内的
rclone是前台运行的,正常情况下Bash会自动回收子进程资源,但调试模式(-xv)或输出重定向的异常可能导致Bash未触发自动回收,rclone退出后变成僵尸。
解决方法
1. 修正Cron启动方式(核心修复)
Cron的@reboot任务本身就是后台执行的,无需额外加&,反而会导致进程脱离正常管控。推荐两种方式让脚本彻底脱离终端:
方案一:用nohup启动
@reboot sleep 900 && nohup /home/creta/Scripts/N1/N1_Docs.sh > /dev/null 2> /home/creta/Scripts/N1/N1_Docs.log &
方案二:用setsid创建独立会话
@reboot sleep 900 && setsid /home/creta/Scripts/N1/N1_Docs.sh > /dev/null 2> /home/creta/Scripts/N1/N1_Docs.log
2. 优化脚本避免潜在问题
- 修正for循环通配符:你给
/D1/N1/*.pdf加了引号,导致通配符无法被Shell展开,无论目录下有没有PDF文件,循环都会执行一次。去掉引号即可:
若要避免目录无PDF时的空循环,可开启for z in /D1/N1/*.pdf; donullglob选项:#!/bin/bash -xv shopt -s nullglob while true; do for z in /D1/N1/*.pdf; do /usr/bin/rclone move /D1/N1/ New:D1/N1/ --log-file=/home/user/Scripts/N1/N1_Docs.log done sleep 18 done - 移除调试模式:脚本开头的
-xv是调试用的,生产环境建议去掉,减少输出干扰:#!/bin/bash
3. 手动清理现有僵尸进程
用ps aux | grep Z找到僵尸进程,再通过ps -o ppid= <僵尸PID>获取其父进程ID,最后执行kill -HUP <父进程ID>或重启对应服务,init/systemd会自动回收僵尸资源。
内容的提问来源于stack exchange,提问作者linux01
相关产品推荐
相关产品推荐

