我有一個相對簡單的 bash 腳本,直接呼叫時效果很好,但由 cron 運行時會失敗。為什麼會失敗以及如何透過 cron 使其工作?
#!/bin/bash
apt-get update -y
apt-get upgrade -y
apt-get install boinc-client -y
一旦 cron 嘗試運行它,手動調用將導致以下錯誤:
dpkg was interrupted, you must manually run 'sudo dpkg --configure -a' to correct the problem.
但只要是第一次手動執行,就可以正常運作。
答案1
此類問題的通常答案是 cron 作業在非互動式、非登入 shell 中運行,因此大多數 shell 啟動檔案(包括/etc
主目錄中的系統範圍檔案和個人點檔案)都不是來源的(讀入並執行) ,因為大多數shell 啟動檔案適用於登入shell(登入電腦時看到的第一個shell)或互動式shell(連接到終端機、ssh 會話或終端模擬器的shell,因為使用者是透過所述終端與他們交互)。
因此,如果您在 cron 作業中放置一個命令,該命令實際上依賴通常發生在、、或 等PATH
位置的某些環境設定(包括更改),則該設定不會在 cron 作業中發生。 cron 檔案格式確實允許您為作業指定環境變量,因此您可能需要指定或將其指向 shell 啟動腳本來源。請參閱手冊頁的「調用」部分。/etc/profile
/etc/bashrc
~/.profile
~/.bashrc
BASH_ENV
ENV
bash(1)
答案2
這不符合答案,但我無法發表評論。建議:
將以下內容新增至您的 bash 腳本中。記錄到郵件輸出的最後一行將是失敗的命令。
set -x set -e
- 確保您有 sendmail (安裝提供的軟體包,例如
postfix
或esmtp
) - 安裝郵件閱讀器(建議
mutt
) - 確保郵件到達您手中
- 透過後綴(可能由安裝程式自動完成):
root: my-user-name
加到/etc/aliases
或/etc/postfix/aliases
- 通過 cron:添加
MAILTO="my-user-name"
到適當的crontab
文件
- 透過後綴(可能由安裝程式自動完成):
- 確保您有 sendmail (安裝提供的軟體包,例如
驗證腳本將在不同的環境中運行。指定 apt-get 的完整路徑(可能不是罪魁禍首,因為已知已找到 apt-get)並在 X 之外的控制台(不是終端)中運行它。
- 修改腳本使用絕對路徑,即
/usr/bin/apt-get update -y
(替換為正確的路徑) - 透過按切換到控制台
ctrl-alt-f1
- 切換到root用戶:
sudo -i
- 在沒有環境的情況下啟動非登入shell:(
env -i /bin/bash --noprofile --norc
替換為正確的路徑) - 運行腳本:
/my/full/path/to/cronscript
.有效嗎?
- 修改腳本使用絕對路徑,即
腳本有權限嗎?你用的是系統的crontab嗎? (再一次,可能不是罪魁禍首)
- 您已聲明您正在使用系統 crontab,因此請跳過此步驟。
apt-get 是否需要會話支援(consolekit 或 systemd)。然而,這只是黑暗中的一槍。
- 知道的不夠多,無法提供協助。
答案3
設法解決它,幾乎不了解發生了什麼。事實證明,即使我從 root crontab 運行,apt-get 命令仍然需要在它們前面加上 sudo。從邏輯上講,我原以為不需要,因為腳本已經以“root”身份執行,但是一旦我添加了 sudo...一切都完全按預期工作。