有時候手工執行Python腳本跑的好好的,但是部署到Linux的crontab中後,就會遇到一些問題,最近終於有空整理一下這方面的內容,其實也是自己也踩了一些別人踩過的坑!這裡僅僅列舉個人遇到的一些小問題,經驗和精力問題,不能面面俱到,僅總結一下自己遇到的這些問題。 環境變數問題 cron中的環境變... ...
有時候手工執行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
還有一種方案,就是使用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) # 設置屏幕上顯示的格式