有时候手动执行Python脚本运行得很好,但是部署到Linux crontab后,就会遇到一些问题。最近终于有时间整理一下这方面的内容。其实我也踩过别人的一些。太糟糕了!这里我只列出一些我遇到的小问题、经验和精力问题。它不可能是详尽无遗的。我只是总结一下我遇到的这些问题。
环境变量问题
cron中的环境变量与系统环境变量不同。我们可以通过设置定时器脚本将cron中的环境变量打印出来,然后对比一下就可以发现不同了
* * * * * env > /tmp/env.txt
如果您想在 Python 脚本中获取环境变量,则在部署到 Crontab 作业后应该小心。很有可能手动运行脚本是正常的,但是部署到Crontab后就无法正常运行了,如下所示,我们构建这样一个测试脚本 crontab_env_www.gyballet.com
# -*- 编码:utf-8 -*-
导入日志记录
导入os.path
导入操作系统
导入base64
# 第一步是创建一个记录器
logger =logging.getLogger()
logger.setLevel(logging.DEBUG) # 日志级别开关
# 第二步是创建一个用于写入日志文件的处理程序
log_path = '/home/konglb/logs/'
log_name = log_path + 'kerry_test.log'
日志文件 = 日志名称
file_handler =logging.FileHandler(logfile, mode='a+')
file_handler.setLevel(logging.ERROR) # 切换到输出日志级别到文件
# 第三步定义handler的输出格式
formatter =logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
file_handler.setFormatter(格式化程序)
# 第四步,将handler添加到logger中
logger.addHandler(file_handler)
# 如果需要同时在终端输出,定义一个streamHandler
print_handler =www.gyballet.comHandler() # 输出到屏幕
print_handler.setFormatter(formatter) #设置屏幕显示的格式
logger.addHandler(print_handler)
db_user=os.environ.get('my_env')
打印(db_user)
logger.error(db_user)
如下所示,如果手动执行脚本,环境变量my_env的值会被写入到/home/konglb/logs/kerry_test.log(export my_env=kerry是在/etc/profile中设置的)
# /usr/local/bin/python3.6 /home/konglb/python/crontab_env_www.gyballet.com
凯里
2019-08-20 20:20:18,293 - crontab_env_www.gyballet.com[行:30] - 错误:kerry
然后我们配置好crontab后,如下图,我们可以通过刷新日志来获取环境变量my_env的值
# crontab -l
*/1 * * * * /usr/local/bin/python3.6 /home/konglb/python/crontab_env_www.gyballet.com
如下图所示,你会看到Crontab中运行的Python脚本根本没有获取到环境变量my_env的值
2019-08-20 20:20:18,293 - crontab_env_www.gyballet.com[行:30] - 错误:kerry
2019-08-20 20:22:02,337 - crontab_env_www.gyballet.com[行:30] - 错误:无
2019-08-20 20:23:01,533 - crontab_env_www.gyballet.com[行:30] - 错误:无
2019-08-20 20:24:01,682 - crontab_env_www.gyballet.com[行:30] - 错误:无
2019-08-20 20:25:01,832 - crontab_env_www.gyballet.com[行:30] - 错误:无
2019-08-20 20:26:01,103 - crontab_env_www.gyballet.com[行:30] - 错误:无
2019-08-20 20:27:01,243 - crontab_env_www.gyballet.com[行:30] - 错误:无
2019-08-20 20:28:01,397 - crontab_env_www.gyballet.com[行:30] - 错误:无
2019-08-20 20:29:01,543 - crontab_env_www.gyballet.com[行:30] - 错误:无
2019-08-20 20:30:01,680 - crontab_env_www.gyballet.com[行:30] - 错误:无
2019-08-20 20:31:01,998 - crontab_env_www.gyballet.com[行:30] - 错误:无
2019-08-20 20:32:01,223 - crontab_env_www.gyballet.com[行:30] - 错误:无
2019-08-20 20:33:01,369 - crontab_env_www.gyballet.com[行:30] - 错误:非
那么如何解决这个问题,如下图,执行Python脚本时,获取/etc/profile中的系统变量(不同平台或环境有所不同)
*/1 * * * * 源 /etc/profile && /usr/local/bin/python3.6 /home/konglb/python/crontab_env_www.gyballet.com
另一种解决方案是使用 shell 来包装 Python 脚本,如下所示:
#!/bin/bash
源/etc/profile
/usr/local/bin/python3.6 /home/konglb/python/crontab_env_www.gyballet.com
*/1 * * * * /home/konglb/python/www.gyballet.com
相对路径问题
修改上面的脚本,使用相对路径,如下图,然后运行crontab作业时就会报错
# -*- 编码:utf-8 -*-
导入日志记录
导入os.path
导入操作系统
导入base64
# 第一步是创建一个记录器
logger =logging.getLogger()
logger.setLevel(logging.DEBUG) # 日志级别开关
# 第二步是创建一个用于写入日志文件的处理程序
#log_path = '/home/konglb/logs/'
log_path = os.path.dirname(os.getcwd()) + '/logs/'
log_name = log_path + 'kerry_test.log'
日志文件 = 日志名称
file_handler =logging.FileHandler(logfile, mode='a+')
file_handler.setLevel(logging.ERROR) # 切换到输出日志级别到文件
# 第三步定义handler的输出格式
formatter =logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
file_handler.setFormatter(格式化程序)
# 第四步,将handler添加到logger中
logger.addHandler(file_handler)
# 如果需要同时在终端输出,定义一个streamHandler
print_handler =www.gyballet.comHandler() # 输出到屏幕
print_handler.setFormatter(formatter) #设置屏幕显示的格式
logger.addHandler(print_handler)
db_user=os.environ.get('my_env')
打印(db_user)
logger.error(db_user)
其实切换到其他路径后,手动执行脚本也会报错。因为相对路径的设置,会出现一些逻辑错误,如下图。因此,如果要将Python脚本部署为Crontab作业,最好使用绝对路径来避免这个问题。
/根
# /usr/local/bin/python3.6 /home/konglb/python/crontab_env_www.gyballet.com
追溯(最近一次调用最后一次):
文件“/home/konglb/python/crontab_env_www.gyballet.com”,第 19 行,位于 File_handler =logging.FileHandler(logfile, mode='a+')
文件“/usr/local/lib/python3.6/logging/__init__.py”,第 1031 行,位于 __init__
StreamHandler.__init__(self, self._open())
文件“/usr/local/lib/python3.6/logging/__init__.py”,第 1060 行,位于 _open
返回 open(self.baseFilename, self.mode, 编码=self.encoding)
FileNotFoundError: [Errno 2] 没有这样的文件或目录: '//logs/kerry_test.log'
另外,还遇到过密码过期导致crontab作业无法执行(Linux账户密码过期会导致crontab作业无法执行)等情况。然而,这与Python脚本无关。如果遇到相关问题,可以参考Why -Cronjob-Not-Work 这篇文章介绍这几个方面来思考、分析和判断。
参考文献: https://www.gyballet.com/2018/10/29/Why-Crontab-Not-Work/
发表评论 (已有0条评论)
还木有评论哦,快来抢沙发吧~