crontab中部署Python脚本注意事项

系统 1830 0

有时候手工执行Python脚本跑的好好的,但是部署到Linux的crontab中后,就会遇到一些问题,最近终于有空整理一下这方面的内容,其实也是自己也踩了一些别人踩过的坑!这里仅仅列举个人遇到的一些小问题,经验和精力问题,不能面面俱到,仅总结一下自己遇到的这些问题。

 

 

环境变量问题

 

cron中的环境变量和系统的环境变量是不一样的,我们可以通过设置定时脚本将cron中的环境变量打印出来,然后一对比,你就能发现差异

 

       * * * * * env > /tmp/env.txt

 

如果你Python脚本中要获取环境变量的话,那么部署到Crontab作业后就要小心了,很有可能手工运行脚本是正常的,但是部署到Crontab后运行就不正常了,如下所示,我们构造这样一个测试脚本crontab_env_test.py

 

              
                #!/usr/bin/python
              
            
              
                # -*- coding: utf-8 -*-
              
            
               
            
              import logging
            
              import os.path
            
              import os
            
              import base64
            
               
            
               
            
               
            
              
                # 第一步,创建一个logger
              
            
              logger = logging.getLogger()
            
              logger.setLevel(logging.DEBUG)  
              
                # Log等级开关
              
            
              
                # 第二步,创建一个handler,用于写入日志文件
              
            
              log_path = 
              
                '/home/konglb/logs/'
              
            
              log_name = log_path + 
              
                'kerry_test.log'
              
            
              logfile = log_name
            
              file_handler = logging.FileHandler(logfile, mode=
              
                'a+'
              
              )
            
              file_handler.setLevel(logging.ERROR)  
              
                # 输出到file的log等级的开关
              
            
              
                # 第三步,定义handler的输出格式
              
            
              formatter = logging.Formatter(
              
                "%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s"
              
              )
            
              file_handler.setFormatter(formatter)
            
              
                # 第四步,将handler添加到logger里面
              
            
              logger.addHandler(file_handler)
            
              
                # 如果需要同時需要在終端上輸出,定義一個streamHandler
              
            
              print_handler = logging.StreamHandler()  
              
                # 往屏幕上输出
              
            
              print_handler.setFormatter(formatter)  
              
                # 设置屏幕上显示的格式
              
            
              logger.addHandler(print_handler)
            
               
            
               
            
              db_user=os.environ.get(
              
                'my_env'
              
              )
            
              print(db_user)
            
              logger.error(db_user)
            

 

如下所示,手工执行该脚本,就会往/home/konglb/logs/kerry_test.log中写入环境变量my_env的值(/etc/profile中设置了export my_env=kerry )

 

# /usr/local/bin/python3.6 /home/konglb/python/crontab_env_test.py

kerry

2019-08-20 20:20:18,293 - crontab_env_test.py[line:30] - ERROR: kerry

 

然后我们配置crontab后,如下所示,通过刷新日志观察其获取环境变量my_env的值

 

# crontab -l

*/1 * * * *   /usr/local/bin/python3.6 /home/konglb/python/crontab_env_test.py

 

如下截图所示,你会看到在Crontab中运行的Python脚本根本没有获取到环境变量my_env的值

 

              
                # tail -60f kerry_test.log 
              
            
              2019-08-20 20:20:18,293 - crontab_env_test.py[line:30] - ERROR: kerry
            
              2019-08-20 20:22:02,337 - crontab_env_test.py[line:30] - ERROR: None
            
              2019-08-20 20:23:01,533 - crontab_env_test.py[line:30] - ERROR: None
            
              2019-08-20 20:24:01,682 - crontab_env_test.py[line:30] - ERROR: None
            
              2019-08-20 20:25:01,832 - crontab_env_test.py[line:30] - ERROR: None
            
              2019-08-20 20:26:01,103 - crontab_env_test.py[line:30] - ERROR: None
            
              2019-08-20 20:27:01,243 - crontab_env_test.py[line:30] - ERROR: None
            
              2019-08-20 20:28:01,397 - crontab_env_test.py[line:30] - ERROR: None
            
              2019-08-20 20:29:01,543 - crontab_env_test.py[line:30] - ERROR: None
            
              2019-08-20 20:30:01,680 - crontab_env_test.py[line:30] - ERROR: None
            
              2019-08-20 20:31:01,998 - crontab_env_test.py[line:30] - ERROR: None
            
              2019-08-20 20:32:01,223 - crontab_env_test.py[line:30] - ERROR: None
            
              2019-08-20 20:33:01,369 - crontab_env_test.py[line:30] - ERROR: Non
            

 

那么要如何解决这个问题呢,如下所示,在执行Python脚本时,获取/etc/profile中的系统变量(不同平台或不同环境有所区别)

 

*/1 * * * * source /etc/profile && /usr/local/bin/python3.6 /home/konglb/python/crontab_env_test.py

 

crontab中部署Python脚本注意事项_第1张图片

 

 

还有一种方案,就是使用shell包裹Python脚本,如下所示:

 

              
                # more kerry.sh 
              
            
               
            
              
                #!/bin/bash
              
            
               
            
              source /etc/profile
            
               
            
              /usr/
              
                local
              
              /bin/python3.6 /home/konglb/python/crontab_env_test.py
            

 

*/1 * * * *     /home/konglb/python/kerry.sh

 

 

相对路径问题

 

把上面的脚本修改一下,使用相对路径,如下所示,然后crontab作业运行时就会报错

 

              
                #!/usr/bin/python
              
            
              
                # -*- coding: utf-8 -*-
              
            
               
            
              import logging
            
              import os.path
            
              import os
            
              import base64
            
               
            
               
            
               
            
              
                # 第一步,创建一个logger
              
            
              logger = logging.getLogger()
            
              logger.setLevel(logging.DEBUG)  
              
                # Log等级开关
              
            
              
                # 第二步,创建一个handler,用于写入日志文件
              
            
              
                #log_path = '/home/konglb/logs/'
              
            
              log_path = os.path.dirname(os.getcwd()) + 
              
                '/logs/'
              
            
              log_name = log_path + 
              
                'kerry_test.log'
              
            
              logfile = log_name
            
              file_handler = logging.FileHandler(logfile, mode=
              
                'a+'
              
              )
            
              file_handler.setLevel(logging.ERROR)  
              
                # 输出到file的log等级的开关
              
            
              
                # 第三步,定义handler的输出格式
              
            
              formatter = logging.Formatter(
              
                "%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s"
              
              )
            
              file_handler.setFormatter(formatter)
            
              
                # 第四步,将handler添加到logger里面
              
            
              logger.addHandler(file_handler)
            
              
                # 如果需要同時需要在終端上輸出,定義一個streamHandler
              
            
              print_handler = logging.StreamHandler()  
              
                # 往屏幕上输出
              
            
              print_handler.setFormatter(formatter)  
              
                # 设置屏幕上显示的格式
              
            
              logger.addHandler(print_handler)
            
               
            
               
            
              db_user=os.environ.get(
              
                'my_env'
              
              )
            
              
                print
              
              (db_user)
            
              logger.error(db_user)
            

 

其实切换到其它路径后,手工执行该脚本也会报错误,因为相对路径的设置,导致一些逻辑错误出现,如下所示,所以如果要部署为Crontab作业的Python脚本,最好使用绝对路径,避免出现这个问题。

 

              
                # pwd
              
            
              /root
            
              
                # /usr/local/bin/python3.6 /home/konglb/python/crontab_env_test.py
              
            
              Traceback (most recent call last):
            
                File 
              
                "/home/konglb/python/crontab_env_test.py"
              
              , line 19, 
              
                in
              
              
            
                  file_handler = logging.FileHandler(logfile, mode=
              
                'a+'
              
              )
            
                File 
              
                "/usr/local/lib/python3.6/logging/__init__.py"
              
              , line 1031, 
              
                in
              
               __init__
            
                  StreamHandler.__init__(self, self._open())
            
                File 
              
                "/usr/local/lib/python3.6/logging/__init__.py"
              
              , line 1060, 
              
                in
              
               _open
            
                  
              
                return
              
               open(self.baseFilename, self.mode, encoding=self.encoding)
            
              FileNotFoundError: [Errno 2] No such file or directory: 
              
                '//logs/kerry_test.log'
              
            

 

 

 

另外,像密码过期导致crontab不执行作业(Linux账号密码过期会导致crontab作业不能执行)这样的案例也遇到过,不过这个与Python脚本无关系,如果遇到相关问题,可以从Why-Cronjob-Not-Work这篇文章介绍的这几个方面去思考、分析判断。

 

 

参考资料

 

  https://www.tony-yin.site/2018/10/29/Why-Crontab-Not-Work/


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论