比較的単純な 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 ジョブは非対話型の非ログイン シェルで実行されるため、ほとんどのシェル スタートアップ ファイル (システム全体のファイル/etc
とホーム ディレクトリ内の個人用ドット ファイルの両方) はソース化 (読み取りおよび実行) されない、というものです。これは、ほとんどのシェル スタートアップ ファイルがログイン シェル (コンピューターにログインしたときに最初に表示されるシェル) または対話型シェル (ユーザーがターミナルを介して対話するため、ターミナル、ssh セッション、またはターミナル エミュレーターに接続されているシェル) に適用されるためです。
したがって、、、、またはなどの場所PATH
で通常行われる環境設定 (変更を含む)に実際に依存するコマンドを cron ジョブに配置すると、その設定は cron ジョブでは行われません。cron ファイル形式ではジョブの環境変数を指定できるため、またはを指定して、ソースとなるシェル起動スクリプトを指すようにすることができます。マニュアル ページの「呼び出し」セクションを参照してください。/etc/profile
/etc/bashrc
~/.profile
~/.bashrc
BASH_ENV
ENV
bash(1)
答え2
これは回答として適格ではありませんが、コメントできません。提案:
次のコードを bash スクリプトの先頭に追加します。メール出力に記録される最後の行が、失敗したコマンドになります。
set -x set -e
postfix
sendmail があることを確認します (またはなどの提供パッケージをインストールしますesmtp
)- メールリーダーをインストールする(推奨
mutt
) - メールが確実に届くようにする
- postfix経由(インストーラーによって自動的に実行される可能性があります):
root: my-user-name
または/etc/aliases
/etc/postfix/aliases
- cron経由:適切なファイル
MAILTO="my-user-name"
に追加crontab
- postfix経由(インストーラーによって自動的に実行される可能性があります):
スクリプトが別の環境で実行されることを確認します。apt-get へのフルパスを指定し (apt-get が見つかったことがわかっているため、おそらく原因ではありません)、X 外部のコンソール (ターミナルではない) で実行します (一部の dpkg configure スクリプトでは X セッションが必要です)。
- 絶対パスを使用するようにスクリプトを変更します
/usr/bin/apt-get update -y
(正しいパスに置き換えます)。 - を押してコンソールに切り替える
ctrl-alt-f1
- ルートユーザーに切り替えます:
sudo -i
- 環境なしで非ログインシェルを起動します:
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 を追加すると、すべてが期待どおりに機能しました。