python定時任務(wù)


一個簡單的需求,即定時啟動python腳本犹褒,這種需求很常見,比如定時啟動一段程序?qū)Ψ?wù)器狀態(tài)進行收集弛针,寫到文件中叠骑,方便運維后期審計,查看服務(wù)器占用高峰時間段削茁,從而判斷出公司產(chǎn)品在該時間段較多人使用宙枷,或定時清除其他程序的日志,釋放線上服務(wù)器的空間茧跋,這塊常見的架構(gòu)是有個轉(zhuǎn)存程序慰丛,將日志通過nginx文件服務(wù)掛起,然后該程序請求這種文件瘾杭,將其存儲在數(shù)據(jù)服務(wù)器中诅病,而線上服務(wù)器的日志就不需要了(游戲日志通常比較大堡牡,所以轉(zhuǎn)存程序也需要設(shè)計一下)房揭。

本章主要來實現(xiàn)一下定時啟動python的需求拄丰,當然吟孙,定時啟動其他任何程序也都一樣。

Python threading模塊

一開始芥永,為了省事篡殷,直接使用python的threading模塊,threading模塊下有個Timer模塊埋涧,它可以實現(xiàn)定時啟動python程序的需求板辽,用法如下:

  1. from threading import Timer

  2. def timedTask():

  3. ? ?print(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))

  4. ? ?main() #主題程序邏輯

  5. ? ?global timer

  6. ? ?timer = Timer(300,timedTask)

  7. ? ?timer.start()


  8. if __name__ == '__main__':

  9. ? ?timedTask()

值得一提的是,timer需要使用global timer飞袋,據(jù)說嘗試運行時戳气,會釋放無需使用的占用資源。

實現(xiàn)方法很簡單巧鸭,即創(chuàng)建Timer()實例瓶您,傳入兩個參數(shù),分別是時間間隔(單位為秒)與定時任務(wù)本身纲仍,構(gòu)成一個死遞歸(因為沒有逃出條件)呀袱,然后就是調(diào)用Timer實例的start()方法。

不推薦郑叠,雖然網(wǎng)上博客說使用global timer會釋放無用資源夜赵,但實際沒有考證,這種寫法在服務(wù)器上跑起來的程序通常一天就斷乡革,我周日啟動該程序寇僧,周一來公司看,對應(yīng)的python程序掛了沸版。

APScheduler

APScheduler是Python用于執(zhí)行定時操作的第三方框架嘁傀,作為一個框架,它就有它對應(yīng)的各種概念视粮,沒必要搞那么復(fù)雜细办,學(xué)習(xí)成本有點高,放棄

Linux crontab

最總還是轉(zhuǎn)到了Linux的crontab服務(wù)蕾殴,該服務(wù)主要就是用于實現(xiàn)定時任務(wù)的笑撞,其語法如下:

  1. # .---------------- minute (0 - 59)

  2. # | ?.------------- hour (0 - 23)

  3. # | ?| ?.---------- day of month (1 - 31)

  4. # | ?| ?| ?.------- month (1 - 12) OR jan,feb,mar,apr ...

  5. # | ?| ?| ?| ?.---- day of week (0 - 6) (Sunday=0 or 7) ?OR

  6. #sun,mon,tue,wed,thu,fri,sat

  7. # | ?| ?| ?| ?|

  8. # * ?* ?* ?* ?* ?command to be executed

  • minute:代表一小時內(nèi)的第幾分,范圍 0-59钓觉。

  • hour:代表一天中的第幾小時茴肥,范圍 0-23。

  • mday:代表一個月中的第幾天荡灾,范圍 1-31炉爆。

  • month:代表一年中第幾個月堕虹,范圍 1-12。

  • wday:代表星期幾芬首,范圍 0-7 (0及7都是星期天)。

  • who:要使用什么身份執(zhí)行該指令逼裆,當您使用 crontab -e 時郁稍,不必加此字段。

  • command:所要執(zhí)行的指令胜宇。

  • crontab服務(wù)狀態(tài)

    1. sudo service crond start ? ? #啟動服務(wù)

    2. sudo service crond stop ? ? ?#關(guān)閉服務(wù)

    3. sudo service crond restart ? #重啟服務(wù)

    4. sudo service crond reload ? ?#重新載入配置

    5. sudo service crond status ? ?#查看服務(wù)狀態(tài)

    查看定時任務(wù)

    1. crontab -l

    到這里耀怜,關(guān)于crontab常見的文件就是叫你使用 crontab-e來編寫對應(yīng)crontab配置文件,配置內(nèi)容的語法如上桐愉,例子如下:

    1. # 每天早上6點

    2. 0 6 * * * echo "Good morning." >> /tmp/test.txt //注意單純echo财破,從屏幕上看不到任何輸出,因為cron把任何輸出都email到root的信箱了从诲。


    3. # 每兩個小時

    4. 0 */2 * * * echo "Have a break now." >> /tmp/test.txt ?


    5. # 晚上11點到早上8點之間每兩個小時和早上八點

    6. 0 23-7/2左痢,8 * * * echo "Have a good dream" >> /tmp/test.txt

    但這邊不會這樣操作,這種寫法并不適合于真正的工作中系洛,就是一個Toy俊性,我希望的是全自動化,這里通過shell腳本來實現(xiàn)自動添加crontab任務(wù)描扯。

    shell腳本代碼如下:

    1. #! /bin/bash


    2. cd LogSys/

    3. work_path=/x1_game/agent_flask/LogSys/


    4. if [ ! -n "$1" ]; then

    5. ? ?echo "Usages: sh startLog.sh [start|stop]"

    6. ? ?exit 0

    7. fi


    8. if [ "$1" = start ] ;then

    9. ? ?if [ ! -x logs ] ;then

    10. ? ? ? ?mkdir logs

    11. ? ?fi

    12. ? ?if [ -f logs/logsys.ini ] ;then

    13. ? ? ? ?echo "logsys task is in crontab, can not add the task to crontab agent!"

    14. ? ? ? ?exit 0

    15. ? ?else

    16. ? ? ? ?echo $(date "+%Y_%m_%d") >> logs/logsys.ini

    17. ? ? ? ?chmod 777 start.sh

    18. ? ? ? ?echo "* * * * * ${work_path}start.sh start >> ${work_path}logs/cron.log 2>&1" >> /var/spool/cron/root

    19. ? ? ? ?echo "add LogSys task to crontab"

    20. ? ?fi


    21. elif [ "$1" = stop ] ;then

    22. ? ?if [ -f logs/logsys.ini ] ;then

    23. ? ? ? ?rm -rf logs/logsys.ini

    24. ? ? ? ?rm -rf /var/spool/cron/root

    25. ? ? ? ?echo "Stop success and remove the logsys.ini"

    26. ? ?else

    27. ? ? ? ?echo "logsys is not running"

    28. ? ?fi

    29. fi

    這是我使用的完整shell腳本定页,這里自動添加crontab任務(wù)的命令只有一行,就是 echo"* * * * * ${work_path}start.sh start >> ${work_path}logs/cron.log 2>&1">>/var/spool/cron/root绽诚,這個命令會每分鐘都會調(diào)用start.sh腳本典徊,而start.sh腳本中啟動了python,幾個坑需要注意恩够,crontab中請使用絕對路徑卒落,因為crontab啟動程序時,相對路徑所對應(yīng)的坐標系其實與你手動啟動該腳本時是不同的玫鸟,使用絕對路徑省事导绷,這里還將star.sh腳本的輸出內(nèi)容都重定向到對應(yīng)的日志文件中。

    為什么不直接通過crontab啟動python程序呢屎飘?而是要再繞一層妥曲,通過shell腳本來啟動,這其實也是一個坑钦购,除非你是單python文件檐盟,不然通常都使用shell腳本的形式啟動python,而不在直接使用crontab來啟動押桃,這同樣是因為crontab啟動的任務(wù)相對路徑的坐標系改變了葵萎,多文件的python項目相互引入文件時,使用的坐標系與crontab啟動時不同,導(dǎo)致crontab直接啟動python項目會失敗羡忘,所以技巧就在于谎痢,通過shell腳本來啟動python程序,在啟動前卷雕,通過cd命令進入python項目對應(yīng)的目錄节猿,這樣就將啟動時的相對路徑的坐標系改成與python的一致了

    具體可以看一下我的start.sh腳本,代碼如下:

    1. #! /bin/bash


    2. currTime=$(date "+%Y_%m_%d")

    3. logfile=${currTime}_logsys.log


    4. if [ ! -n "$1" ]; then

    5. ? ?echo "Usages: sh start.sh [start|stop]"

    6. ? ?exit 0

    7. fi


    8. if [ ! -x logs ] ;then

    9. ? ?mkdir logs

    10. fi


    11. pid=`ps -ef | grep log2mysql | grep -v grep|awk '{print $2}'`


    12. if [ "$1" = start ] ;then

    13. ? ?if [ -n "$pid" ] ;then

    14. ? ? ? ?echo "log2mysql is running, can not start"

    15. ? ? ? ?exit 0

    16. ? ?fi

    17. ? ?cd /x1_game/agent_flask/LogSys/

    18. ? ?nohup /usr/local/bin/python -u log2mysql.py >> logs/$logfile 2>&1 &

    19. ? ?pid=`ps -ef | grep log2mysql | grep -v grep|awk '{print $2}'`

    20. ? ?echo "start log2mysql, pid is:"$pid

    21. elif [ "$1" = stop ] ;then

    22. ? ?if [ -n "$pid" ] ;then

    23. ? ? ? ?echo "kill log2mysql, pid is: "$pid

    24. ? ? ? ?kill -9 $pid

    25. ? ?else

    26. ? ? ? ?echo "log2mysql is not running "$pid

    27. ? ?fi

    28. fi

    通過python啟動任務(wù)的關(guān)鍵命令在于

    1. cd /x1_game/agent_flask/LogSys/

    2. nohup /usr/local/bin/python -u log2mysql.py >> logs/$logfile 2>&1 &

    首先會進入要啟動python項目的所在目錄漫雕,然后再通過python啟動對應(yīng)的py文件滨嘱,這里使用python解釋器同樣要使用全路徑,因為線上系統(tǒng)中存在多個python浸间,因為該python程序是耗時程序太雨,所以我希望它在后臺運行,所以使用了 nohup&關(guān)鍵字魁蒜,將其放在后臺去運行囊扳。

    題外話:centos系統(tǒng)中的yum是依賴python的,具體到centos6梅惯,其yum依賴系統(tǒng)本身就存在的python2.6宪拥,但開發(fā)環(huán)境通常要使用python2.7,此時最好不要刪除系統(tǒng)中自帶的python2.6铣减,如果你直接刪除她君,會導(dǎo)致yum使用不了,此時就需要修改一下yum對應(yīng)文件中的python指向葫哗,最好的方法就是直接安裝python2.7缔刹,然后在/usr/bin下創(chuàng)建對應(yīng)的軟連接來使用。

    小結(jié)

    python程序員在工作中其實不能只會python劣针,因為python雖然強大校镐,但也會有其缺陷,所以什么好用捺典,用什么才是對的鸟廓,還有python是一種語言,不要被語言局限襟己。

    ?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
    • 序言:七十年代末引谜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子擎浴,更是在濱河造成了極大的恐慌员咽,老刑警劉巖,帶你破解...
      沈念sama閱讀 217,277評論 6 503
    • 序言:濱河連續(xù)發(fā)生了三起死亡事件贮预,死亡現(xiàn)場離奇詭異贝室,居然都是意外死亡契讲,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
      沈念sama閱讀 92,689評論 3 393
    • 文/潘曉璐 我一進店門滑频,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捡偏,“玉大人,你說我怎么就攤上這事峡迷∨恚” “怎么了?”我有些...
      開封第一講書人閱讀 163,624評論 0 353
    • 文/不壞的土叔 我叫張陵凉当,是天一觀的道長。 經(jīng)常有香客問我售葡,道長看杭,這世上最難降的妖魔是什么? 我笑而不...
      開封第一講書人閱讀 58,356評論 1 293
    • 正文 為了忘掉前任挟伙,我火速辦了婚禮楼雹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尖阔。我一直安慰自己贮缅,他們只是感情好,可當我...
      茶點故事閱讀 67,402評論 6 392
    • 文/花漫 我一把揭開白布介却。 她就那樣靜靜地躺著谴供,像睡著了一般。 火紅的嫁衣襯著肌膚如雪齿坷。 梳的紋絲不亂的頭發(fā)上桂肌,一...
      開封第一講書人閱讀 51,292評論 1 301
    • 那天,我揣著相機與錄音永淌,去河邊找鬼崎场。 笑死,一個胖子當著我的面吹牛遂蛀,可吹牛的內(nèi)容都是我干的谭跨。 我是一名探鬼主播,決...
      沈念sama閱讀 40,135評論 3 418
    • 文/蒼蘭香墨 我猛地睜開眼李滴,長吁一口氣:“原來是場噩夢啊……” “哼螃宙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起悬嗓,我...
      開封第一講書人閱讀 38,992評論 0 275
    • 序言:老撾萬榮一對情侶失蹤污呼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后包竹,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體燕酷,經(jīng)...
      沈念sama閱讀 45,429評論 1 314
    • 正文 獨居荒郊野嶺守林人離奇死亡籍凝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
      茶點故事閱讀 37,636評論 3 334
    • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了苗缩。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饵蒂。...
      茶點故事閱讀 39,785評論 1 348
    • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖酱讶,靈堂內(nèi)的尸體忽然破棺而出退盯,到底是詐尸還是另有隱情,我是刑警寧澤泻肯,帶...
      沈念sama閱讀 35,492評論 5 345
    • 正文 年R本政府宣布渊迁,位于F島的核電站,受9級特大地震影響灶挟,放射性物質(zhì)發(fā)生泄漏琉朽。R本人自食惡果不足惜,卻給世界環(huán)境...
      茶點故事閱讀 41,092評論 3 328
    • 文/蒙蒙 一稚铣、第九天 我趴在偏房一處隱蔽的房頂上張望箱叁。 院中可真熱鬧,春花似錦惕医、人聲如沸耕漱。這莊子的主人今日做“春日...
      開封第一講書人閱讀 31,723評論 0 22
    • 文/蒼蘭香墨 我抬頭看了看天上的太陽螟够。三九已至,卻和暖如春沛简,著一層夾襖步出監(jiān)牢的瞬間齐鲤,已是汗流浹背。 一陣腳步聲響...
      開封第一講書人閱讀 32,858評論 1 269
    • 我被黑心中介騙來泰國打工椒楣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留给郊,地道東北人。 一個月前我還...
      沈念sama閱讀 47,891評論 2 370
    • 正文 我出身青樓捧灰,卻偏偏與公主長得像淆九,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子毛俏,可洞房花燭夜當晚...
      茶點故事閱讀 44,713評論 2 354

    推薦閱讀更多精彩內(nèi)容