2011-12-09

crontab 實作心得

由於常常忘記錄節目,在友人的批評及建議之下,嘗試使用 crontab。

科技始於人性

關於忘記錄節目這件事是這樣的。朋友自己寫了一個叫做 "dvb" 的 shell script,可以在當天或好幾天前,指定日期、時間錄下數位電視頻道的節目,可是我懶得去指定日期,總是當天才下指令,問題是有的「當天」會忘記下達指令,就漏錄了。與其怨嘆自己的記性,不如把這件事交給 crontab。crontab 會把固定要做的事情辦得好好的。

開工

我的系統版本是
$ cat /etc/debian_version
5.0.9
$ uname -r
2.6.27.59
首先以 root 的身分,建立並編寫 /etc/cron.allow 這個檔案(因為我的系統裡沒有這個檔案),內容只有幾個字母,也就是我的使用者名稱。這麼做之後,就可以持使用者的身分做以下的事情。
首先是編寫工作排程:
$ crontab -e
這樣就進入編寫排程的介面。編寫完畢,儲存並離開編輯程式,就生效了。以下是我的排程內容(這裡假設程式放在 /usr/local/sh/ 之下,因此實際上出了問題,請看後解):
# m h dom mon dow command
59 22 * * 1 cd /tv/ && /usr/local/sh/dvb -R5
59 22 * * 2 cd /tv/ && /usr/local/sh/dvb -R5
59 22 * * 3 cd /tv/ && /usr/local/sh/dvb -R5
59 22 * * 4 cd /tv/ && /usr/local/sh/dvb -R5
26 18 * * 0 cd /tv/ && /usr/local/sh/dvb -E 1827-1857 ttv-1
這裡排的工作共有五項,前四行是要錄周一到周四公視的《國際換日線》,最後一行是錄周日的《海賊王》。為了把錄下來的節目集中在某個資料夾,所以先換到 /tv/ 資料夾,再啟動朋友寫的預錄節目的 shell script "/usr/local/sh/dvb",dvb 後面的參數,"-R5" 是告訴這個 shell script(不是 crontab)錄當天公視的《國際換日線》,最後一個錄《海賊王》的參數比較長,是因為這個節目不在該 script 的預設錄影節目裡,必須手動給出錄影始末時間及指定電視台。

數字

每行是一件工作。這些數字、字母的意思逐項是分、時、日、月、星期、程式執行工作,這六欄兩兩之間以空格或 tab 分開,最後一欄全部是程式用,語法之間的空白無所限制。這裡要執行的工作是規定每個禮拜幾的幾點幾分要錄節目。雖然執行工作的程式已規定錄影時間,但是也得要跟 crontab 約定好下達指令的時間,否則要是在分、時的地方只以 * 號表示(表示所有數字)而沒有給它一個數字,那麼就等於告訴它每分鐘都執行一次排給它的工作,接下來信箱每分鐘都會收到報告工作啟動的信件,相當可怕,而且事實上這裡是要錄節目,也無法接連不停展開多個錄影程序。所以不管是以禮拜還是月、日為單位做排程時,幾點幾分要記得寫(除非就是要驚人的每分鐘)。

另外關於幾月幾日與禮拜幾這兩組計算方式不同的單位,通常是不會同時都設定的,因為 crontab 取的是聯集而非交集,要是都給數字,它會照單全收,幾月幾日和禮拜幾都會執行,除非就是要這樣排程(應該很少見……),否則將遠離初衷。

關於數字表示法,禮拜天以 0 或 7 表示。數字之表示還有這樣的:0-3,6,11-20,這是不連續時的寫法,還有,*/2、*/3、2-20/4,這是取指定的數字,每 2 或 3 或 4 個單位執行一次的意思,也就是除號吧。

路徑

接下來是一件很重要的事,也就是執行工作用的程式的路徑寫法(也就是上面所說的「後解」),最好/必須是完整路徑。雖然在某些情形下(這樣或那樣),工作欄位裡的程式路徑寫完整就沒問題,但有時候自己寫的程式,並未在程式裡寫出該程式的完整路徑,如此一來,即使在工作欄位裡寫的明明是完整路徑,但 crontab 工作時,進入該程式後卻會很困擾,於是回報狀況時會非常簡明地寫道「sh: line 行數: 程式名稱: command not found」,這意思就是,它沒辦法做下去。就算要改程式一時之間也太大費周章了,這時的解決辦法是讓 crontab 的預設路徑(PATH)裡也有該程式所在的資料夾。crontab 的預設路徑(它認得的)只有 /usr/bin 和 /bin,想要加上自己的路徑,只要在進入 crontab 排程的編輯模式之後,於所有排程開始之前,也就是最上面,加上一行來修改預設路徑即可,其內容包括它原先認得的以及新加入的,例如:
PATH=/usr/bin:/bin:/usr/local/bin:/usr/local/sh
隨你加多長。如果要加入的路徑是在自己家裡,則必須寫完整路徑,不能以「$HOME」帶過。然而,在排程裡,自己家裡則可以寫做「$HOME」。要改 shell 也是在這裡,寫在 PATH 的上一行,寫成「SHELL=/bin/什麼sh」即可。

其他參數

如果只是要看 crontab 排了什麼工作,指令是這樣的:
$ crontab -l
螢幕上會很乖巧地秀出預定的工作(但是不會秀出預設路徑):
# m h dom mon dow command
59 22 * * 1 cd /tv/ && /usr/local/sh/dvb -R5
59 22 * * 2 cd /tv/ && /usr/local/sh/dvb -R5
59 22 * * 3 cd /tv/ && /usr/local/sh/dvb -R5
59 22 * * 4 cd /tv/ && /usr/local/sh/dvb -R5
26 18 * * 0 cd /tv/ && /usr/local/sh/dvb -E 1827-1857 ttv-1
除了路徑設定部分之外,跟編輯時鍵入的東西長得一模一樣。而如果要看別的使用者所排的工作,權限允許的話,指令是這樣:
$ crontab -u username -l
再來另一個參數:
$ crontab -r
這是不進入編輯模式,直接把所有排定的工作都殺掉。

到此應該算是入門完滿吧。相關的 manpage 如下:
$ man crontab
$ man 5 crontab
$ man cron

No comments:

Post a Comment