為什麼我的 crontab 腳本不工作?

為什麼我的 crontab 腳本不工作?

我試圖透過 crontab 運行儲存在我的主目錄中的腳本,但它不起作用。每次執行時,CRON 日誌都會顯示以下內容:

Sep  3 18:30:01 backup CRON[6778]: (root) CMD (/home/hannes/script > /tmp/yc.log)
Sep  3 18:30:01 backup CRON[6777]: (CRON) info (No MTA installed, discarding output)

定時任務:

*/1 * * * * /home/hannes/script > /tmp/yc.log

如果我嘗試添加 .sh 檔案副檔名,它不會改變任何內容。 yc.log 檔案保持為空。

這是我嘗試執行的腳本(如果我手動運行它,效果很好):

#!/bin/sh
cp -r -p mnt/main-nas/PATH-TO-FILE mnt/backup-nas/01/temp/server
zip -r mnt/backup-nas/01/1.19_Test.`date +%d.%m.%Y_%H.%M.%S`.zip mnt/backup-nas/01/temp/server
rm -r mnt/backup-nas/01/temp/server

任何幫助表示讚賞! :)

答案1

你的腳本實際上正在運行...但它在某個地方出錯了。由於您不捕獲stderr輸出,因此 stderr 會傳送cron給在本機執行腳本的使用者。 (也失敗了)

根本原因是:您的腳本僅重定向stdout到檔案。然而,許多失敗的腳本和程式都用來stderr輸出錯誤訊息。您需要透過新增到執行2>&1的命令列末尾來捕獲該錯誤cron,這也將捕獲stderr錯誤並將錯誤記錄到您的檔案中。

因為您之前沒有捕獲到它,所以 stderr 是通過郵件傳遞到的root- 但因為您沒有用於本地傳遞的本地MTA(郵件傳輸代理,又名本地郵件傳輸協議(LMTP) 伺服器),所以您收到了這些cron 錯誤。透過stderr捕獲,您現在將看到錯誤以及腳本無法正常運行的原因。

一旦日誌中出現錯誤輸出,您就可以進一步偵錯腳本以確定需要執行哪些操作來「修復」問題。

答案2

所以有幾個問題。首先,我忘記添加2>&1末尾/home/hannes/script > /tmp/yc.log,以便實際保存日誌。其次,我的腳本中有一個拼字錯誤,我忘記了所有路徑中的第一個斜線。事情就從這樣變成home/hannes/...這樣了/home/hannes/...。我希望這可以幫助其他遇到類似問題的人,並感謝所有回覆的人:)

答案3

接受的答案是正確的並且涵蓋了所述問題。然而,問題中提供的資訊表明該腳本存在一個不相關的潛在問題,我認為警告OP很重要,並且正確解釋它對於評論來說太長了,所以我專門添加了一個答案來涵蓋這一點。


除了日誌記錄問題之外,您的安排還存在潛在的嚴重競爭條件。由於腳本始終使用相同的目錄來暫存要歸檔的文件,因此如果腳本的多個實例同時運行,則第一個運行的實例可能會刪除任何後續實例當前正在處理的文件,從而導致額外的失敗並且很可能是不完整的存檔(因為檔案在zip處理它們之前就會消失)。

這可以透過兩種方式之一解決,腳本本身應該使用每次呼叫目錄,或者應該使用檔案鎖定來防止並發運行。

第一種方法要容易得多,您只需將日期添加到您正在使用的目錄中即可。看起來像這樣(請注意,這也確保只date調用一次):

#!/bin/sh
now="$(date +%d.%m.%Y_%H.%M.%S)"
cp -r -p mnt/main-nas/PATH-TO-FILE mnt/backup-nas/01/temp/server/${now}
zip -r mnt/backup-nas/01/1.19_Test.${now}.zip mnt/backup-nas/01/temp/server/${now}
rm -r mnt/backup-nas/01/temp/server/${now}

文件鎖定方法有點複雜,但可以說更乾淨,因為它還確保您不會意外地因zip同時運行多個命令而淹沒系統。這涉及使用一個名為flock(Ubuntu 和 Debian 上的軟體包的一部分util-linux,已安裝)的命令,看起來像這樣(帶有註釋來解釋發生了什麼):

#!/bin/sh
# All of this gets run in a subshell so we can hold a file descriptor open
# for all the commands. We're using file descriptor 9 here, but any number
# higher than 2 will work.
(
    # This flock command is what actually takes the lock. The lock itself 
    # persists until the file descriptor is closed when the subshell exits.
    # The -x means it's an exclusive lock (so only one instance can hold it).
    # The -w says to try for that many seconds before failing if something
    # else is holding the lock (this is an important safety net to ensure you
    # don’t get a long queue of these scripts waiting to run).
    # The -n indicates which file descriptor to take the lock on.
    flock -x -w 30 -n 9 || exit 1
    cp -r -p mnt/main-nas/PATH-TO-FILE mnt/backup-nas/01/temp/server
    zip -r mnt/backup-nas/01/1.19_Test.`date +%d.%m.%Y_%H.%M.%S`.zip mnt/backup-nas/01/temp/server
    rm -r mnt/backup-nas/01/temp/server
# And this line closes the subshell, and also sets the path to be used for
# the lock file by opening it as file descriptor 9 for the subshell. /run
# is generally the place you want to put stuff like this, because it will
# get cleaned up automatically every time the system reboots.
) 9> /run/backup-nas.lock

相關內容