伺服器部署python指令碼並使用crontab定時執行

Deep_Rayne發表於2020-11-10

生命不息,折騰不止。
前幾日做了一個python指令碼用於每天疫情簽到。想試著用伺服器每天定點執行。
折騰了一天,算是成了,給大家分享一下踩坑,尤其時Crontab!!

伺服器設定

首先,我們使用鈔能力搞一臺伺服器,不管是華為、騰訊、阿里的伺服器價格都差不多。在這裡我選了騰訊的。安裝Ubuntu 20.04 LTS:
在這裡插入圖片描述
按照騰訊說明配置好SSH後使用putty登入伺服器:
在這裡插入圖片描述
使用python3 --version系統已經內建了python3.8.5:
在這裡插入圖片描述
但是沒裝pip3:

sudo apt-get install python3-pip

在這裡插入圖片描述

至此環境配置完成

程式碼執行嘗試

首先將程式碼上傳至/home/ubuntu目錄下,我們可以使用WinSCP上傳檔案。為了更方便的除錯程式碼,可以使用Pycharm遠端連線除錯。但程式碼每次都無法同步,還是建議本地除錯好直接上傳。
我的程式碼分為兩個指令碼,runer.py和login.py。runer.py為入口,依賴login.py。我們嘗試使用命令執行:

python3 runer.py

發現缺少lxml及相關包,使用pip3安裝:

sudo pip3 install lxml
...

這裡有一個天坑!不要用pip3 install lxml,這樣在正常情況下也能用,用python3 *.py可以執行,但是crontab執行會有問題!

Crontab除錯

crontab很難伺候,不管是環境還是指令碼地址都需要絕對路徑,因此我們使用一個.sh檔案作為入口:

#start.sh檔案,位於/home/ubuntu/sign/下
cd /home/ubuntu/sign
python3 runer.py >> hist

首先跳入我們的指令碼地址,這樣就不會出找不到指令碼了。
注意,一定要指定python直譯器版本,如果你有兩個python3,你需要指定到python的位置!
crontab沒有輸出視窗,因此我們可以把程式碼中print的內容儲存在同級目錄中的hist檔案。

接下來配置crontab。首先開啟crontab設定介面:

sudo crontab -e

配置格式可參見https://www.runoob.com/w3cnote/linux-crontab-tasks.html

在這裡,建議開啟日誌記錄,自帶日誌需要配置syslog,且不會記錄執行出錯的內容,例如python找不到包之類的錯誤,因此建議自己配置日誌輸出
我配置的結果:

00 08 * * * sudo bash /home/ubuntu/sign/start.sh > /home/ubuntu/sign/log 2>&1 &

意思是每日早上8點執行,錯誤日誌輸出至同級的目錄的log檔案。
在除錯時我們可以設定一個每分鐘執行一次的任務:

*/1 * * * * sudo bash /home/ubuntu/sign/start.sh > /home/ubuntu/sign/log 2>&1 &

重啟crontab:

sudo service cron restart

觀察日誌檔案是否有異常,或者沒生成日誌檔案。
現在講一下這個天坑!用pip3和sudo pip3安裝包的區別:
我弄好之後,發現我的指令碼無法執行,於是我新增了一個test.py的命令,輸出一行字到hist檔案中,test可以執行。檢視log發現是沒找到lxml包,WTF我不是安裝了嗎,於是,我手動執行了該任務,也就是.sh檔案裡的:

python3 runer.py >> hist

沒錯,能執行,很多網上的教程告訴我們說是python直譯器不對,crontab預設的是usr/bin下面的。沒錯,很多錯誤都是這個原因,但這個不同,我用的就是usr/bin/python3。於是我檢視了python3:

python3
>>>import lxml

發現可以匯入,但是crontab不行!
我們繼續輸入:

>>> import sys
>>> sys.path

得到依賴包的位置集合:

['', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', 
'/home/ubuntu/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages',
'/usr/local/lib/python3.8/dist-packages/cloud_init-20.1-py3.8.egg',
 '/usr/lib/python3/dist-packages']

看看lxml包位置:

import lxml
print(lxml)

發現包的位置在/usr/.local/lib/…下。如果我們用sudo執行,必須在usr/local/…才對!
重新用sudo安裝lxml,成功執行!

相關文章