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


9

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

私の計画は、IPアドレスをまだ持っていないときにループし、持っているときに続行することです。重要なのは、しばらくするとタイムアウトになることです。私が思いついたのはですがif [ ifconfig | grep "192.168.100" ];、何が起こるかは、grepがを消費し、];それが気に入らないことです。それからbashも動揺します、なぜならそれは];どの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...

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


1
initがsystemdの場合、待機するサービスファイルを記述しますnetwork-online.target...
jasonwryan

grep出力をにリダイレクトする必要はありません/dev/null-q代わりにオプションを使用してください。また、ifconfigをgrepするのは良い考えではありません。ping代わりに使用しないのはなぜですか?
ラッシュ

ping問題のネットワークによっては失敗する可能性があります。システムの実行構成を確認するだけの方が良いでしょう。
Bratchley 2014

回答:


8

シェル構文

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

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

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

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

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

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

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がある場合…

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


私はそうする/net/べきだと思います/proc/netか?
sebix 2015年

@sebixいいえ、なぜでしょうか?Linuxのネットワーク構成について話しているのではありません。リモートファイルシステムのマウントポイントの例を/net挙げます。このようなマウントポイントの一般的な場所です。
Gilles「SO-邪悪なことをやめよう」

では、マウントされたネットワークドライブが必要です。より一般的なソリューションも存在しますか?
sebix 2015年

@sebix何のためのソリューション?マウントされたネットワークドライブの要求は目標の例であり、ソリューションの例ではありませんでした。
Gilles「SO-邪悪なことをやめなさい」

1

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.