nohup.out 不能直接被 logrotate 安全轮转,因其依赖进程持续持有文件描述符,rename 方式会导致日志写入重命名后的旧文件;copytruncate 有竞态风险;推荐用定时脚本“先拷贝后清空”,并严格统一时间格式、时区、路径权限与清理逻辑。

nohup.out 不能直接被 logrotate 切割?
因为 nohup.out 是进程持续写入的打开文件,logrotate 默认用 rename + create 新文件方式轮转,但原进程仍持有旧文件描述符(fd),继续往已被重命名的文件里写——导致日志“消失”或写入错误位置。这不是配置问题,是 Linux 文件描述符机制决定的。
所以别在 logrotate 配置里硬加 nohup.out,它不支持 copytruncate 以外的常规轮转模式,而 copytruncate 有竞态风险(写入中截断可能丢几行)。
用定时脚本手动切割 + 清空是最稳的方案
参考你知识库中已验证的生产脚本逻辑,关键在于「先拷贝、再清空」,而非重命名或移动:
-
cp /data/media/wvp/nohup.out /data/media/wvp/logs_nohup/nohup_$(date -d '-1 hours' '+%Y年%m月%d日%H时').log—— 拷贝时文件内容已落盘,安全 -
cat /dev/null > /data/media/wvp/nohup.out—— 清空操作原子且无竞态,进程 fd 不变,后续日志继续追加到空文件 - 务必确保目标目录
/data/media/wvp/logs_nohup/存在且有写权限,否则脚本静默失败 - crontab 中建议用绝对路径调用
date,避免某些最小化系统里/usr/bin/date和/bin/date不一致
crontab 定时执行要注意时区和时间精度
脚本每小时执行一次,但 crontab 默认按系统本地时区解析时间。如果你服务器时区是 UTC,而业务日志要按北京时间归档(如“2026年09月08日10时”),就得显式指定:
- 在 crontab 前加
TZ=Asia/Shanghai,或 - 脚本内用
date -d '-1 hours' -u '+%Y年%m月%d日%H时'配合TZ=Asia/Shanghai环境变量 - crontab 条目示例:
0 * * * * TZ=Asia/Shanghai /bin/bash /data/media/wvp/scripts/rotate_nohup.sh - 避免用
@hourly,它等价于0 * * * *,但部分 cron 实现对@hourly的时区处理不一致
清理老日志时 date 命令的格式必须严格匹配
删除命令:rm -rf /data/media/wvp/logs_nohup/nohup_$(date -d '-3 days' '+%Y年%m月%d日')*.log 依赖文件名前缀完全一致。一旦某次脚本因时间偏差或时区错乱生成了 2026年09月05日09时.log,而清理脚本只删 2026年09月05日*.log,就会漏掉。
更健壮的做法是:
- 统一用
%Y%m%d这类无分隔符格式(如20260905),避免中文/符号引发 glob 匹配失败 - 清理前先
find /data/media/wvp/logs_nohup -name 'nohup_????????*.log' -mtime +3 -delete,靠文件修改时间而非文件名判断 - 加个简单校验:
ls -1 /data/media/wvp/logs_nohup/nohup_*.log 2>/dev/null | wc -l,如果远超预期数量,说明前面某步出错了
真正麻烦的不是切割动作本身,而是确保每次执行时时间计算、路径存在性、权限、编码(比如中文日期在某些 locale 下会乱码)全部对齐。线上跑稳的前提,是把所有隐含依赖都显式写死。


















