Python脚本通过Cron@reboot执行无效的问题排查与修复
问题描述
- Python脚本
/home/debian/project/del_video.py手动执行正常,代码如下:
#!/usr/bin/env python3 # -*- coding:utf-8 -*- import os import time today = time.strftime("%w",time.localtime()) video_dir = '/home/ftpuser/ftp_dir/upload/6J078DEGAG56788' if today == '5': for item in os.listdir(video_dir): if item != 'DVRWorkDirectory': del_dir = os.path.join(video_dir,item) os.system('sudo /usr/bin/rm -rf {} '.format(del_dir))
- 发布当日为周五,手动执行
/usr/bin/python3 /home/debian/project/del_video.py可正常删除目标目录内文件。 - 将脚本加入crontab:
crontab -e
添加内容:
@reboot /usr/bin/python3 /home/debian/project/del_video.py
- 重启系统后文件未被删除,
cron.log无报错:
Jul 28 09:46:29 debian cron[756]: (CRON) INFO (Running @reboot jobs) Jul 28 09:46:31 debian CRON[825]: (debian) CMD (/usr/bin/python3 /home/debian/project/del_video.py) Jul 28 09:49:06 debian crontab[2218]: (debian) BEGIN EDIT (debian) Jul 28 09:50:38 debian crontab[2218]: (debian) END EDIT (debian) Jul 28 09:53:35 debian crontab[2694]: (debian) BEGIN EDIT (debian) Jul 28 09:55:01 debian CRON[2739]: (root) CMD (command -v debian-sa1 > /dev/null && debian-sa1 1 1) Jul 28 09:57:56 debian crontab[2694]: (debian) END EDIT (debian)
- 功能相同的Bash脚本
project/del_video.sh可正常运行,代码如下:
dw=$(date +%w) video_dir='/home/ftpuser/ftp_dir/upload/6J078DEGAG56788' if [[ $dw = 5 ]]; then for item in $(ls "$video_dir");do if [[ $item != DVRWorkDirectory ]];then sudo /usr/bin/rm -rf "$video_dir"/"$item" fi done fi
- 已在
/etc/sudoers中给debian用户设置免密sudo权限:
debian ALL=(ALL:ALL) NOPASSWD:ALL
修复方案
1. 解决@reboot时目录未挂载的问题
@reboot任务执行时机较早,可能目标存储目录还未完成挂载,导致脚本找不到目录。有两种解决方式:
方法A:添加启动延迟
修改Python脚本,在开头加入等待时间(比如30秒),确保存储设备挂载完成:
#!/usr/bin/env python3 # -*- coding:utf-8 -*- import os import time # 等待30秒,确保目录挂载完成 time.sleep(30) today = time.strftime("%w",time.localtime()) video_dir = '/home/ftpuser/ftp_dir/upload/6J078DEGAG56788' if today == '5': for item in os.listdir(video_dir): if item != 'DVRWorkDirectory': del_dir = os.path.join(video_dir,item) # 改用subprocess替代os.system,便于捕获执行信息 import subprocess subprocess.run(['sudo', '/usr/bin/rm', '-rf', del_dir])
方法B:改用systemd服务(更可靠)
创建/etc/systemd/system/del-video.service文件:
[Unit] Description=Delete old video files on reboot After=multi-user.target network.target mount.target [Service] Type=oneshot User=debian ExecStart=/usr/bin/python3 /home/debian/project/del_video.py [Install] WantedBy=multi-user.target
执行以下命令启用服务:
sudo systemctl daemon-reload sudo systemctl enable del-video.service
2. 替换os.system为subprocess并添加日志
原脚本使用os.system无法捕获命令执行错误,改用subprocess并添加日志输出,方便排查问题:
#!/usr/bin/env python3 # -*- coding:utf-8 -*- import os import time import subprocess import logging # 配置日志文件,记录执行过程 logging.basicConfig(filename='/var/log/del_video.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') try: time.sleep(30) today = time.strftime("%w", time.localtime()) video_dir = '/home/ftpuser/ftp_dir/upload/6J078DEGAG56788' logging.info(f"当前星期值:{today},检查目录:{video_dir}") # 先判断目录是否存在 if not os.path.exists(video_dir): logging.error(f"目标目录不存在:{video_dir}") exit(1) if today == '5': for item in os.listdir(video_dir): if item != 'DVRWorkDirectory': del_path = os.path.join(video_dir, item) logging.info(f"开始删除:{del_path}") # 捕获命令输出,方便排查错误 result = subprocess.run(['sudo', '/usr/bin/rm', '-rf', del_path], capture_output=True, text=True) if result.returncode != 0: logging.error(f"删除失败:{del_path},错误信息:{result.stderr}") else: logging.info("今日非周五,无需执行删除操作") except Exception as e: logging.error(f"脚本执行出错:{str(e)}")
3. 测试时验证星期值逻辑
测试阶段可以临时修改脚本中的星期判断条件(比如当天是周一就改成today == '1'),确保脚本逻辑能正常触发。
内容的提问来源于stack exchange,提问作者showkey
相关产品推荐
相关产品推荐

