シェルスクリプトのwhileループ

シェルスクリプトのwhileループ

count コマンドを実行できますが、while 条件内で使用するとエラーが発生します。

-bash: [/usr/bin/ps -aef|/usr/bin/egrep 'catalina|java|wrapper-linux-x86-64'|/usr/bin/grep -v 'catalina|java|wrapper-linux-x86-64'|wc -l: No such file or directory.


count="/usr/bin/ps -aef|/usr/bin/egrep 'catalina|java|wrapper-linux-x86- 
64'|/usr/bin/grep -v 'catalina|java|wrapper-linux-x86-64'|wc -l"
while [ "$count" -ne 0 ]
do
echo "killing services and tomcat process"
/usr/bin/ps -aef|/usr/bin/egrep "catalina|java|wrapper-linux-x86- 
64"|/usr/bin/grep -v "catalina|java"|/usr/bin/awk '{print 
$2}'|/usr/bin/xargs kill -9
sleep 10
count="/usr/bin/ps -aef|/usr/bin/egrep 'catalina|java|wrapper-linux-x86- 
64'|/usr/bin/grep -v 'catalina|java|wrapper-linux-x86-64'|wc -l"

done;

答え1

count="/usr/bin/ps -aef|...|wc -l"

変数にコマンドを保存しないでください。変数はそのために設計されておらず、保存されたコマンドで作業することは困難です。コマンドをどこかに保存するには、次の関数を使用します。

count_procs() {
    /usr/bin/ps -aef|...|wc -l
}

関数は他のコマンドのように使用できます。

表示されるコードは、対応するcount文字列の値を整数ゼロと比較します。 Bashは[数値以外の値について文句を言います。

発生したエラーは、同様のコマンド(["$count" -eq 0 ]および間にスペースがない)で発生する可能性があります。これは、その内容が連結され、実行されるコマンドの名前であるコマンドラインの最初の単語を形成するためです。これは愚かですが、括弧、パイプ文字、スペースを含むパスを持つことは完全に可能です。[$countcount[

さて、実際にコマンドを実行し、その出力をキャプチャしてゼロと比較したいと仮定すると、コマンド置換を使用する必要があります$(...)

result=$(ps ... |wc -l)            # save the output of the command to `result`

または

[ "$(ps ... | wc -l)" -eq 0 ] ... # use the command output directly in a test

ループが実行されるたびにプロセス数を計算するには、ループ本体内でコマンドを実行する必要があります。例えば

while [ "$(ps ... | wc -l)" -eq 0 ]; do
    ...
done

または関数を使用してください。

count_procs() {
    /usr/bin/ps -aef|...|wc -l
}
while [ "$(count_procs)" -eq 0 ]; do
    ...
done  

ループの前にプロセスを一度だけ計算すると、条件は一定になり、ループは無限に繰り返されるかまったく繰り返されません。

答え2

whileループではcount変数を減らす必要があります。

count=10
while [ $count -ne 0 ]; do
    echo "Count is $count"
    ((count--))
done

実際の算術を実行するには、次のようないくつかの方法があります。

  • ((count--))
  • ((count-=1))
  • ((count=count-1))
  • count=$((count - 1))

二重括弧構造の詳細については、次を参照してください。https://www.linuxtopia.org/online_books/advanced_bash_scripting_guide/dblparens.html

以下も使用できますlet

  • let "count--"
  • let "count-=1"
  • let "count=count-1"

詳細については、次をlet参照してください。http://wiki.bash-hackers.org/commands/buildin/let


編集する:と同じ機能を持たないPOSIX互換シェルに関する注意事項bash

Posixシェルはこの構文を使用できます$(( <expression> ))。したがって、上記と同じループがあり、kshCAE Issue 4(XPG4)などのシェルまたは公式のポータブルシェルで動作していることを確認したい場合sh

  • count=$((count - 1))

これが重要な場合は、この構文を使用すると、bash関連の構文を使用するよりもスクリプトの移植性が高くなります。

答え3

コマンドの代替引用符の混同に加えて、エラーメッセージはwhile ["$count" -ne 0]実際には角かっこの周りに必要なスペースがないことを示します。覚えておいてください。 「while」の後ろの部分は実際には注文するとループが終わったら注文する0以外の状態で終了(参照https://www.gnu.org/software/bash/manual/bashref.html#Looping-Constructs)。

空白がないため、bashは

while ["/usr/bin/ps -aef|/usr/bin/egrep 'catalina|java|wrapper-linux-x86-64'|/usr/bin/grep -v 'catalina|java|wrapper-linux-x86-64'|wc -l" -ne 0]

実行しようとしています。注文する ["/usr/bin/ps -aef|...|wc -l"明らかに見つからなかったようです

これが[実際には注文するしたがって、最初の引数とコマンド名を区別するには、コマンド名の後にスペースを追加する必要があります。 (文を書く理由ls -lと書かない理由は同じですls-l)。命令はまた[これが]彼のものでなければならないことを要求します。最後したがって、パラメータ]もスペースで区切る必要があります。

Bashプロンプトで、およびhelp [help testまたhelp [[)を入力します。

答え4

主な問題は、次の二重引用符を使用することです。

$(...)

この部分についていくつかのコメントがあります(コメントが長すぎます)。

while [ "$count" -ne 0 ]
do
echo "killing services and tomcat process"
done;

  • ループには停止メカニズムはありませんwhile。たとえば、次のようになります。

    count=$(( count - 1 ))
    
  • スタイリングの観点から見るとしなければならない内部空間。

  • 最後にセミコロンは必要ありません。

関連情報