Linuxマシンのリストでpingアクセスを確認するために、次のbashスクリプトを作成しました。
for M in $list
do
ping -q -c 1 "$M" >/dev/null
if [[ $? -eq 0 ]]
then
echo "($C) $MACHINE CONNECTION OK"
else
echo "($C) $MACHINE CONNECTION FAIL"
fi
let C=$C+1
done
これは印刷します:
(1) linux643 CONNECTION OK
(2) linux72 CONNECTION OK
(3) linux862 CONNECTION OK
(4) linux12 CONNECTION OK
(5) linux88 CONNECTION OK
(6) Unix_machinetru64 CONNECTION OK
次の形式で出力するために、bashスクリプトでprintf
(またはその他のコマンド)をどのように使用できますか?
(1) linux643 ............ CONNECTION OK
(2) linux72 ............. CONNECTION OK
(3) linux862 ............ CONNECTION OK
(4) linux12 ............. CONNECTION OK
(5) linux88 ............. CONNECTION FAIL
(6) Unix_machinetru64 ... CONNECTION OK
パラメータ拡張を使用して、%-s
から生じるスペースをドットで置き換える:
#!/bin/bash
list=(localhost google.com nowhere)
C=1
for M in "${list[@]}"
do
machine_indented=$(printf '%-20s' "$M")
machine_indented=${machine_indented// /.}
if ping -q -c 1 "$M" &>/dev/null ; then
printf "(%2d) %s CONNECTION OK\n" "$C" "$machine_indented"
else
printf "(%2d) %s CONNECTION FAIL\n" "$C" "$machine_indented"
fi
((C=C+1))
done
_for m in $list
_はzsh
構文です。 bash
では、_for i in "${list[@]}"
_になります。
bash
にはパディング演算子はありません。 printf
を使用してパディングを行うことができますが、スペースのみを使用でき、任意の文字は使用できません。 zsh
にはパディング演算子があります。
_#! /bin/zsh -
list=(
linux643
linux72
linux862
linux12
linux88
Unix_machinetru64
)
c=0
for machine in $list; do
if ping -q -c 1 $machine >& /dev/null; then
state=OK
else
state=FAIL
fi
printf '%4s %s\n' "($((++c)))" "${(r:25::.:):-$machine } CONNECTION $state"
done
_
padding演算子は${(r:25:)parameter}
to right-pad with length 25 with spaceまたは${(r:25::string:)parameter}
to right =-スペースの代わりに任意の文字列を埋め込む。
また、_printf '%4s'
_を使用してleft -_(x)
_にスペースを入れます。代わりに${(l:4:):-"($((++c)))"}
を使用することもできます。ただし、大きな違いは、文字列が4文字を超える場合、${(l)}
は文字列を切り捨て、printf
でオーバーフローすることです。
%s
形式指定子は精度(%.20s
など)、浮動小数点値を特定の精度で出力する場合と同様に(%.4f
たとえば)、出力は指定された文字列引数からの最大でその数の文字になります。
したがって、マシン名とドットが足りなくなるほどのドットを含む文字列を作成します。
cnt=0
for hname in vboxhost ntp.stupi.se example.com nonexistant; do
if ping -q -c 1 "$hname" >/dev/null 2>&1; then
status="OK"
else
status="FAIL"
fi
printf "(%d) %.20s CONNECTION %s\n" \
"$(( ++cnt ))" "$hname ...................." "$status"
done
出力:
(1) vboxhost ........... CONNECTION OK
(2) ntp.stupi.se ....... CONNECTION OK
(3) example.com ........ CONNECTION OK
(4) nonexistant ........ CONNECTION FAIL
私はfping
とawk
でそれを行います。残念ながら、awk
のprintf
はドットで埋めることはできず、スペースまたはゼロでのみ埋め込むことができるため、関数を作成する必要があります。
list=(kali surya indra ganesh durga hanuman nonexistent)
fping "${list[@]}" 2>&1 |
sort -k3 |
awk -F'[: ]' 'BEGIN { fmt="(%02d) %s CONNECTION %s\n"};
function dotpad(s,maxlen, l,c,pads) {
l = maxlen - length(s);
pads = "";
for (c=0;c<l;c++) {pads=pads"."};
return s " " pads
};
/alive$/ { printf fmt, ++i, dotpad($1,19), "OK" };
/unreachable$/ { printf fmt, ++i, dotpad($1,19), "FAIL" }
/not known$/ { printf fmt, ++i, dotpad($1,19), "IMPOSSIBLE" } '
(01) durga .............. CONNECTION OK
(02) ganesh ............. CONNECTION OK
(03) indra .............. CONNECTION OK
(04) kali ............... CONNECTION OK
(05) nonexistent ........ CONNECTION IMPOSSIBLE
(06) hanuman ............ CONNECTION FAIL
(07) surya .............. CONNECTION FAIL
かっこ内にゼロを埋め込んだ2桁の数字を使用しているので、$list
に10〜99のホストがある場合にフォーマットが台無しになりません(100以上では台無しになります)。別の方法としては、END {}
ブロックまで印刷を遅らせ、/ regexp-matches /でホスト名を3つの配列のいずれかに挿入するだけです。 ok
、fail
、unknown
。または1つの連想配列(例:hosts[hostname]="OK"
)。次に、行数をカウントし、それを使用して、行カウンターフィールドの幅を決定します。
また、出力で不明なホスト(CONNECTION IMPOSSIBLE
)と到達できないホスト(CONNECTION FAIL
)を区別することにしました。
sort -k3
はオプションであり、fping
の結果( "hostname is alive"、 "hostname is unreachable"または "hostname:Name or service notknown")によって出力をグループ化するだけです。 sort
がない場合、不明なホストは常に出力の最初に表示されます。 -k3
のない単純なsort
は、ホスト名でソートされます。
@chorobaの答えから盗まれたもので:
#!/bin/bash
list=(linux643 linux72 google.com linux862 linux12 linux88 unix_machinetru64)
C=1
readonly TOTAL=50
for M in "${list[@]}"
do
DOTS=$(( TOTAL - ${#M} ))
ping -q -c 1 "$M" &>/dev/null
if (($?)) ; then
printf "(%d) %s" "$C" "$M" ; printf "%0.s." $(seq 1 $DOTS) ; printf " CONNECTION FAILED\n"
else
printf "(%d) %s" "$C" "$M" ; printf "%0.s." $(seq 1 $DOTS) ; printf " CONNECTION OK\n"
fi
((C=C+1))
done