zoukankan      html  css  js  c++  java
  • crontab中部署Python脚本注意事项

    有时候手工执行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

     

    clip_image001

     

     

    还有一种方案,就是使用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 <module>
        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/

  • 相关阅读:
    Oracle基础知识整理
    linux下yum安装redis以及使用
    mybatis 学习四 源码分析 mybatis如何执行的一条sql
    mybatis 学习三 mapper xml 配置信息
    mybatis 学习二 conf xml 配置信息
    mybatis 学习一 总体概述
    oracle sql 语句 示例
    jdbc 新认识
    eclipse tomcat 无法加载导入的web项目,There are no resources that can be added or removed from the server. .
    一些常用算法(持续更新)
  • 原文地址:https://www.cnblogs.com/kerrycode/p/11386074.html
Copyright © 2011-2022 走看看