
我試圖透過 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