Cron任务未执行日志轮换的问题排查求助
我编写了一段带日志轮换功能的Python脚本:当data.log文件大小超过100KB时执行日志轮换操作。直接在周日16-17点通过命令行运行时一切正常,但通过Cron定时任务(规则00 16 * * *)运行时,仅打印「********** New execution starts **********」,虽进入logCheck函数却未完成日志轮换,此时data.log已超过1.5MB。运行环境为Red Hat Enterprise Linux Server。
脚本代码如下:
import os, sys import os.path from datetime import datetime # log rotation if above 1MB def logCheck(): if os.path.getsize('data.log') > 100000: print(f'Performing log rotation') os.remove('data_old.log') if os.path.exists('data_old.log') else None os.rename('data.log', 'data_old.log') sys.exit(0) print(f'********** New execution starts **********') now = datetime.now() if now.strftime("%A") == 'Sunday' and now.strftime("%H") == '16': logCheck() print(f'Script execution starts') ***other code***
Cron任务配置:
00 16 * * * /usr/local/bin/python3 /absolute_path/script.py
1. 相对路径导致日志文件找不到
Cron的默认工作目录是执行用户的主目录(如/home/username),而非脚本所在的/absolute_path/。脚本中使用'data.log'这类相对路径时,Cron运行时会去主目录查找文件,自然找不到目标文件,os.path.getsize会抛出异常,但脚本未做异常捕获,直接导致函数退出,无法执行后续轮换操作。
解决方法:
- 方法一:在脚本开头切换工作目录到脚本所在路径:
# 脚本开头添加 os.chdir(os.path.dirname(os.path.abspath(__file__))) - 方法二:所有文件路径使用绝对路径,例如将
'data.log'改为'/absolute_path/data.log','data_old.log'同理。
2. 时区不匹配(可能性较低)
Cron使用系统默认时区,Python的datetime.now()也依赖系统时区,若系统时区与预期不一致,可能导致now.strftime("%A") == 'Sunday'判断失效。不过你提到已进入logCheck函数,这条可能性稍低,但可排查:
- 在Cron任务中指定时区,例如添加
TZ=Asia/Shanghai(替换为你需要的时区),或直接修改系统时区; - 在脚本中打印当前时间及时区,确认是否符合预期:
print(f"当前时间: {now}, 时区: {datetime.now().astimezone().tzinfo}")
3. 权限不足
Cron执行任务的用户(默认是当前用户)可能没有data.log所在目录的读写权限,或无法删除/重命名data_old.log。
解决方法:
- 检查
/absolute_path/目录和日志文件的权限,确保Cron执行用户拥有读、写、执行权限; - 在Cron任务中指定有权限的用户,例如:
00 16 * * * username /usr/local/bin/python3 /absolute_path/script.py
4. 未捕获异常导致无报错信息
脚本的logCheck函数未做异常处理,一旦os.path.getsize或文件操作抛出异常,会直接终止函数,且无法看到错误信息。
解决方法:
- 给
logCheck添加异常捕获,打印错误详情:def logCheck(): try: if os.path.getsize('data.log') > 100000: print(f'Performing log rotation') if os.path.exists('data_old.log'): os.remove('data_old.log') os.rename('data.log', 'data_old.log') sys.exit(0) except Exception as e: print(f"logCheck执行错误: {str(e)}") sys.exit(1) - 修改Cron任务,将输出重定向到日志文件以便排查:
00 16 * * * /usr/local/bin/python3 /absolute_path/script.py >> /absolute_path/cron_script.log 2>&1
内容的提问来源于stack exchange,提问作者KnowledgeSeeeker

