ルーターを再起動し、コンピュータがインターネットに再接続されるまで進行状況バーを表示する簡単なスクリプトを作成しました。
スクリプトを実行すると、次の結果が表示されます。
The router is now rebooting...
############################################bin/reboot_router: line 48: 4758 Alarm clock: 14 ping -Q -c 1 -t 1 google.com >&/dev/null
#bin/reboot_router: line 48: 4761 Alarm clock: 14 ping -Q -c 1 -t 1 google.com >&/dev/null
#bin/reboot_router: line 48: 4763 Alarm clock: 14 ping -Q -c 1 -t 1 google.com >&/dev/null
#####bin/reboot_router: line 48: 4773 Alarm clock: 14 ping -Q -c 1 -t 1 google.com >&/dev/null
#bin/reboot_router: line 48: 4775 Alarm clock: 14 ping -Q -c 1 -t 1 google.com >&/dev/null
##bin/reboot_router: line 48: 4777 Alarm clock: 14 ping -Q -c 1 -t 1 google.com >&/dev/null
#
そんなことが発生するのを抑えたいAlarm clock: 14
ので、出力は次のようになります。
The router is now rebooting...
#######################################################
スクリプトの関連部分は次のとおりです。
#!/bin/bash
COLUMNS=$(tput cols)
# Reboot router code here
echo 'The router is now rebooting...'
min_time=60
max_time=120
start_time=$SECONDS
time=0
progress=0
until [[ $min_time -lt $time ]] && ping -Q -c 1 -t 1 google.com &> /dev/null; do
let time=SECONDS-start_time
let new_progress=COLUMNS*time/max_time
let diff=new_progress-progress
let progress=new_progress
for((i=0; i<diff; i++)); do
echo -n '#'
done
sleep 1
done
echo
答え1
問題は、pingコマンドに-t 1
pingが1秒後に放棄されるように指示するコマンドが含まれていることです。これにより、SIGALRM
pingが内部的に信号をキャプチャできなくなります。 (これは間違いなくpingエラーですが学術的です。)bashシェルはこれを128(「シグナルをキャッチしました」フラグ)+ 14(SIGALRM ID)のAlarm clock: 14
終了状態にプロセスを中断します。142
この問題を解決する方法は2つあります。
1) -t 1
SIGALRMが生成されないように削除する。代わりに、pingは(私の経験では)5秒以内にタイムアウトし、現在見ているものとは異なるエラー状態を提供します。指定されたホストに接続できない場合、68が発生する可能性があります。この場合、ホストに到達するとすぐにシャットダウンするようにpingに「-o」を追加することもできます。
2) trap - SIGALRM
ping コマンドの前に実行し、シェルにシグナルを無視するよう指示します。 1秒のタイムアウトが引き続き発生し、終了状態が維持されます142
。少なくとも私はYosemite(10.10.5)を実行しているiMacでこれをテストしました。
答え2
それを独自の機能にドラッグし、ping
そこから結果として必要に応じて実行します。最後に、関数内部の状態に応じて0または1が返されます。
ping_func(){
results=$(ping -c 1 -t 1 google.com &> /dev/null)
return $?
}
until [[ $min_time -lt $time ]] && ping_func; do
let time=SECONDS-start_time
let new_progress=COLUMNS*time/max_time
let diff=new_progress-progress
let progress=new_progress
for((i=0; i<diff; i++)); do
echo -n '#'
done
sleep 1
done
echo
case/switch
または、別の状態をインポートするときに別の操作を実行する必要がある場合は、関数内でより詳細な関数を使用できますping
。
case "$status" in
1) return 0 ## success ;;
0) return 1 ## fail ;;
*) ### do something else ;;
esac