為什麼這個腳本在從 cron 運行時失敗,但在手動運行時有效?

為什麼這個腳本在從 cron 運行時失敗,但在手動運行時有效?

我有一個相對簡單的 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~/.bashrcBASH_ENVENVbash(1)

答案2

這不符合答案,但我無法發表評論。建議:

  1. 將以下內容新增至您的 bash 腳本中。記錄到郵件輸出的最後一行將是失敗的命令。

    set -x
    set -e
    
    • 確保您有 sendmail (安裝提供的軟體包,例如postfixesmtp
    • 安裝郵件閱讀器(建議mutt
    • 確保郵件到達您手中
      • 透過後綴(可能由安裝程式自動完成):root: my-user-name加到/etc/aliases/etc/postfix/aliases
      • 通過 cron:添加MAILTO="my-user-name"到適當的crontab文件
  2. 驗證腳本將在不同的環境中運行。指定 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.有效嗎?
  3. 腳本有權限嗎?你用的是系統的crontab嗎? (再一次,可能不是罪魁禍首)

    • 您已聲明您正在使用系統 crontab,因此請跳過此步驟。
  4. apt-get 是否需要會話支援(consolekit 或 systemd)。然而,這只是黑暗中的一槍。

    • 知道的不夠多,無法提供協助。

答案3

設法解決它,幾乎不了解發生了什麼。事實證明,即使我從 root crontab 運行,apt-get 命令仍然需要在它們前面加上 sudo。從邏輯上講,我原以為不需要,因為腳本已經以“root”身份執行,但是一旦我添加了 sudo...一切都完全按預期工作。

相關內容