web-dev-qa-db-ja.com

bashスクリプトでネットワークを待つ

ネットワークの稼働とネットワーク共有のマウントに依存するスクリプトを実行しています。スクリプトはログイン時に実行されます(起動後に自動的に実行されます)。問題は、スクリプトの実行時には、通常、まだIPアドレス(DHCP)をまだ持っていないことです。現時点では15秒間スクリプトをスリープ状態にしているだけですが、何か問題があるかどうかをユーザーに通知できるようにしたいので、このアプローチはまったく好きではありません。

私の計画は、IPアドレスをまだ持っていないときにループし、持っているときに続行することです。重要なのは、しばらくしてタイムアウトになることです。私が思いついたのはif [ ifconfig | grep "192.168.100" ];ですが、grepが];を使用していて好きではないのです。次に、brepも動揺します。これは、grepが食べた];が見つからないためです。そして、私もタイムアウトを実装していません。

誰かが変数を保持し、たとえば各反復で1秒間スリープし、この変数を毎回増やすことを提案しました。これが私の完全な(機能しない)スクリプトです(私はbashスクリプトにかなり慣れていません)。

x=0
while [ ifconfig | grep "192.168.100." > /dev/null ]; do
    echo "no nework"
    if "$x" -gt 200; then
        #Time out here
        exit 1
    x=$((x+1))
    sleep .1
    fi
done

#continue with rest of script...

正しい方向のポインタがあれば大歓迎です!

9
aguywithsocks

シェル構文

シェルスクリプトの条件について混乱しているようです。すべてのシェルコマンドには、0〜255の整数である終了ステータスがあります。0は成功を意味し、その他の値は失敗を意味します。 ifwhile のようなステートメントは、ブールオペランドがコマンドの終了ステータスを検査し、0(成功)をtrueおよびその他の値(失敗)はfalse。

たとえば、grepコマンドは、パターンが見つかった場合は0を返し、パターンが見つからなかった場合は1を返します。そう

while ifconfig | grep "192.168.100." > /dev/null; do …

ifconfigの出力にパターン192.168.100.が見つかる限り、ループを繰り返します。正規表現の192.168.100.は任意の文字に一致するため、パターン192x168 1007.のような文字列に一致することに注意してください。リテラル文字列を検索するには、オプション-Fgrepに渡します。条件を反転するには、!を前に置きます。

while ! ifconfig | grep -F "192.168.100." > /dev/null; do …

さらにスクリプトでは、変数の値を数値と比較したいとします。 -gt演算子を使用します。これは、 test コマンドによって理解される 条件式 の構文の一部です。 testコマンドは、条件式が真の場合は0を返し、条件式が偽の場合は1を返します。

if test "$x" -gt 200; then

通常、testコマンドには代替名[を使用します。この名前は、コマンドがパラメーター]で終わることを想定しています。このコマンドを書く2つの方法はまったく同じです。

if [ "$x" -gt 200 ]; then

Bashは、特別な構文[[ … ]]を使用して、このコマンドを記述する3番目の方法も提供します。 [は通常の構文解析規則に従う通常のコマンドであり、[はシェル構文の一部であるため、この特別な構文は[[ … ]]よりもいくつかの演算子をサポートできます。

繰り返しますが、[条件式用であり、-n-gt、…[のような演算子を使用した構文は、「ブール値」:どのコマンドにもブール値があります(終了ステータス= 0?)。

ネットワークが稼働していることの検出

ネットワークが稼働していることを検出する方法は堅牢ではありません。特に、ネットワークインターフェースが指定された範囲内のIPアドレスを取得するとすぐにスクリプトがトリガーされることに注意してください。特に、マウントされているネットワーク共有は言うまでもなく、その時点ではまだDNSが稼働していない可能性があります。

誰かがログインしたときにこれらのコマンドを実行する必要がありますか?ネットワークが立ち上がったときにコマンドを自動的に実行させる方が簡単です。その方法は、ディストリビューションとNetworkManagerを使用するかどうかによって異なります。

これらのコマンドをログインスクリプトの一部として実行する必要がある場合は、IPアドレスの存在ではなく、本当に必要なリソースをテストしてください。たとえば、/net/somenode/somedirがマウントされているかどうかをテストする場合は、

while ! grep -q /net/somenode/somedir </proc/mounts; do
  sleep 1
done

Upstartまたはsystemdがある場合…

その後、それを使用できます。たとえば、 with Upstart の場合、ジョブをstart on net-device-up eth0としてマークします(eth0は、目的のネットワーク接続を提供するインターフェースの名前に置き換えます)。 Systemdを使用する場合は、 ネットワークの開始後にスクリプトを実行させるのか? を参照してください。

ip add showの出力を数えるだけです。次に例を示します。

root@xxxxxxlp01 ~ $ ip add sh dev eth3 | grep inet
root@xxxxxxlp01 ~ $ ip add sh dev eth1 | grep inet
root@xxxxxxlp01 ~ $ ip add sh dev eth0 | grep inet
    inet xxx.xxx.64.91/24 brd xxx.xxx.95.255 scope global eth0
    inet6 fe80::224:e8ff:fe78:4dfb/64 scope link
root@xxxxxxlp01 ~ $ ip add sh dev eth0 | grep inet | wc -l
2

その後、必要に応じて、返された行数で分岐できます。おそらく、それがゼロかどうかを確認し、ゼロの場合はスリープしてループを繰り返します。

説明のための未テストのコード:

while [ 1 ]; do

  if [ $(ip add sh dev eth0 | grep inet | wc -l) -ne 0 ]; then
     break
  fi

  sleep 1

done
1
Bratchley

Pingは、少なくとも1回の試行が成功した場合、0応答を返します。接続が成功するまで、接続先のサーバーにpingを実行することを検討してください。

1
brwtx