スクリプトを cron ジョブとして実行すると、環境変数が認識されません。

スクリプトを cron ジョブとして実行すると、環境変数が認識されません。

( ) cronjob からスクリプトを呼び出すと、root「ipset が見つかりません」というメッセージが表示されて失敗します。問題のあるスクリプト行は次のとおりです。

for i in $(cat /etc/cn.zone); do ipset -A china $i; done

スクリプト内の数行前でこのコマンドが呼び出されます:

ipset -N china hash:net

したがって、問題の ipset は実際に作成されました。

このスクリプトをルートのホーム ディレクトリから実行すると、問題なく実行されます。

エラーの原因は何だと思いますか?

答え1

スクリプトを cron ジョブとして実行すると、環境変数が認識されません。

( ) cronjob からスクリプトを呼び出すrootと、「ipset が見つかりません」というメッセージが表示されて失敗します…

このスクリプトを Bash スクリプトとして実行していますか? これは最近のほとんどのシェル スクリプトと同じですか?

もしそうなら、スクリプトの最初の行を

#!/bin/bash

これに対して:

#!/bin/bash -l

を追加すると、-lBash はログイン シェルとして呼び出されたかのように実行されます。また、その cron ジョブで Bash スクリプトがログイン シェル経由で実行されると、通常ログイン シェル経由で設定されるすべての環境変数やその他の項目がその Bash スクリプトで使用できるようになり、ipset期待どおりに実行できるようになります。


whichもう一つのトリックは、次のように Bash 変数内で使用することです。明らかにこれを使用している$(cat /etc/cn.zone)ので、メカニズムは似ています。

$(which ipset)

スクリプト内の行を次のように変更します。

for i in $(cat /etc/cn.zone); do $(which ipset) -A china $i; done

これは、 を使用してwhich、これを実行しているシステム上の への完全なパスipset( など/sbin/ipset) をスクリプトに指定します。 次に、 を介してそれを解析された変数として設定すると、$()スクリプト自体がそれを実行できるようになります。

ipsetただし、スクリプトの他の場所で使用する場合、このwhich方法を使用する場合は、スクリプトをリファクタリングして、ipsetスクリプトの先頭近くで次のように変数として設定することをお勧めします。

ipset_bin=$(which ipset);

そして、次のようにコマンドを呼び出します。

$ipset_bin -N china hash:net

この:

for i in $(cat /etc/cn.zone); do $ipset_bin -A china $i; done

答え2

シェルは、環境によって設定されているが、同じ環境を共有していない をipset調べることで、実行可能ファイルがどこにあるかを認識します。PATHcron

これを (またはスクリプトの) の先頭に追加すると、crontab期待どおりにコマンドがどこにあるかがわかります。

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

関連情報