while loop no shell script

0

Eu sou capaz de executar o comando count, mas quando eu uso em while, está dando erro:

-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;
    
por RAJ METRE 03.10.2018 / 13:59

6 respostas

3

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

Não armazene comandos em variáveis, elas não são feitas para isso e usar o comando armazenado é difícil. Se você quiser armazenar o comando em algum lugar, use uma função:

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

Uma função pode ser usada como qualquer outro comando.

O código que você mostrou irá comparar o valor dessa string em count contra zero como um inteiro. O [ do Bash se queixaria de um valor não numérico.

O erro que você apresentou viria de um comando como ["$count" -eq 0 ] (sem espaço entre [ e $count ), pois nesse caso, o conteúdo de count é concatenado com [ para formar o primeira palavra da linha de comando, o nome do comando a ser executado. Embora seja bobagem fazer isso, é perfeitamente possível ter um caminho que contenha colchetes, caracteres de canal e espaço em branco.

Agora, supondo que você queira realmente executar o comando e capturar sua saída para comparar com zero, será necessário usar a substituição de comando $(...) :

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

ou

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

Supondo que você queira contar os processos toda vez que o loop for executado, você terá que execute o comando dentro do corpo do loop. Então, por exemplo

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

ou, com uma função

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

Apenas contar os processos uma vez antes do loop tornaria a condição uma constante, e o loop repetiria indefinidamente, ou não o faria.

    
por 03.10.2018 / 14:51
2

No seu loop while, você precisa diminuir sua variável de contagem.

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

Para a aritmética real, existem várias maneiras de fazer isso, como:

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

Para mais informações sobre construções de parênteses duplos, consulte: link

Você também pode usar let :

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

Para mais informações sobre let , consulte: link

Editar : Uma nota sobre shells compatíveis com POSIX que não possuem os mesmos recursos sofisticados que bash .

As conchas Posix podem usar a sintaxe $(( <expression> )) . Então, se você tivesse o mesmo loop acima, e você quisesse garantir que funcionaria em um shell como ksh , ou shell oficialmente portátil como o sh do CAE Issue 4 (XPG4):

  • count=$((count - 1))

Usar essa sintaxe tornará seu script mais portátil do que usar a sintaxe específica do bash, se isso for importante para você.

    
por 03.10.2018 / 14:17
1

Além da confusão sobre a substituição de comando, a mensagem de erro indica que você realmente tem while ["$count" -ne 0] sem o espaço necessário ao redor dos colchetes. Tenha em mente que a parte depois de "while" é na verdade um comando , e o loop termina quando o comando sai com um status diferente de zero (ref link ).

Devido ao espaço ausente, o bash vê

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]

e está tentando executar o comando ["/usr/bin/ps -aef|...|wc -l" , que obviamente não foi encontrado

É importante lembrar que [ é, na verdade, um comando e, portanto, um espaço depois de ser necessário separar o nome do comando de seu primeiro argumento. (mesmo motivo que você escreve ls -l e não ls-l ). Além disso, o comando [ requer que ] seja seu argumento último , portanto ] também precisa da separação dos espaços em branco.

Em um prompt bash, digite help [ e help test (e também help [[ )

    
por 03.10.2018 / 18:41
1

Mais simples:

while pkill -f 'catalina|java|wrapper-linux-x86-64'; do 
  sleep 10
done

Ainda não é seguro matar processos com base em sua lista de argumentos.

    
por 03.10.2018 / 18:51
0

Seu principal problema é o uso de aspas duplas onde deve haver:

$(...)

Eu tenho algumas observações sobre essa parte (muito longa para um comentário):

while [ "$count" -ne 0 ]
do
echo "killing services and tomcat process"
done;
  • Não há mecanismo de parada para o loop while como:

    count=$(( count - 1 ))
    
  • De um ponto de estilo, você deve espaçar a parte interna.

  • Apenas para observar, você não precisa de um ponto-e-vírgula no final.

por 03.10.2018 / 15:05
-1

substituir

count="..."

com

count='...'
    
por 03.10.2018 / 14:21