ネットワークブートとネットワーク共有マウントに依存するスクリプトを実行しています。このスクリプトはログイン時に実行されます(起動後に自動的に発生します)。問題は、スクリプトの実行時に通常はまだIPアドレス(DHCP)がないことです。現在、スクリプトを15秒間休止状態にしておきますが、問題が発生した場合はユーザーに通知できるようにしたいので、このアプローチはまったく気に入らません。
私の計画は、まだIPアドレスがない場合を繰り返し、IPアドレスがあれば続けることです。決定的に一定の時間が経過するとタイムアウトが発生するはずです。私が見つけたのは、grepがそれを消費し、それを好きではないif [ ifconfig | grep "192.168.100" ];
ということです。そうすれば、bashもどんなgrepを食べたのかを];
見つけることができないので怒ります。];
もしそうなら、まだタイムアウトを実装していません。
何人かの人々は変数を維持し、各反復ごとにしばらく寝て、毎回変数を増やすことを提案しました。これはうまくいかない完全なスクリプトです(私は初めて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
シェル構文
シェルスクリプトの条件について混乱しているようです。すべてのシェルコマンドには、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
.
-F
grep
!
while ! ifconfig | grep -F "192.168.100." > /dev/null; do …
スクリプトで変数の値を数値と比較しようとしています。-gt
構文の一部である演算子を使用します。条件式次のように理解されるtest
注文する。test
条件式がtrueの場合、コマンドは0を返し、条件式がfalseの場合は1を返します。
if test "$x" -gt 200; then
通常、[
コマンドの代替名がtest
使用されます。名前には、コマンドがパラメーターで終わる必要があります]
。このコマンドを作成する方法はどちらも同じです。
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
起動またはシステム化されている場合...
それからそれを使うことができます。例えば、ヌーボーリッチと、タスクをstart on net-device-up eth0
(eth0
必要なネットワーク接続を提供するインターフェイス名に置き換えます)としてマークします。 Systemdの使用を参照してください。ネットワークの起動後にスクリプトが実行されるようにしますか?
答え2
このコマンドを使用できますhostname
。
オプションを使用すると、-I
DHCPサーバーから返されるアドレスであるローカルIPアドレスが取得されます。
hostname -I
# (if has network) return: 192.168.100 or other IP local
次の非常に簡単な例を確認してください。
while [ "$(hostname -I)" = "" ]; do
echo -e "\e[1A\e[KNo network: $(date)"
sleep 1
done
echo "I have network";
私はそれについて考え、他の答えを確認しました。
サーバー接続を確認したい場合があります。
同じスクリプトをコピーしていますが、今はサーバーへの接続を待っています。
# ip server
serverAdr="192.168.0.1"
ping -c 1 $serverAdr > /dev/null 2>&1
while [ $? -ne 0 ]; do
echo -e "\e[1A\e[K $(date): Connecting - ${serverAdr}"
sleep 1
ping -c 1 $serverAdr > /dev/null 2>&1
done
echo "$(date): Connected - ${serverAdr}";
答え3
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
その後、必要に応じて返された行数を分岐できます。 0であることを確認し、そうであればスリープ状態でループを繰り返すことができます。
説明のためにテストされていないコード:
while [ 1 ]; do
if [ $(ip add sh dev eth0 | grep inet | wc -l) -ne 0 ]; then
break
fi
sleep 1
done
答え4
@fitorecの拡張スクリプトバージョン
無限ループを防ぐには、max_countを設定してください。
PS:ビジボックス版には「ping -i」はありません...
接続テスト.sh
# ip server
serverAdr="10.0.0.3"
count=0
count_max=10
ping -c 1 $serverAdr > /dev/null 2>&1
while [ $? -ne 0 ]; do
echo -e "\e[1A\e[K $(date): test connection [$count/$count_max] - ${serverAdr}"
sleep 1
let "count+=1"
[[ ${count} -gt ${count_max} ]] && exit 1
ping -c 1 $serverAdr > /dev/null 2>&1
done
echo "$(date): Connected - ${serverAdr}"
exit 0
使用:
./test_connect.sh || echo "ERROR !!"