Como faço para passar comandos shell complicados por SSH para serem executados remotamente? Mine lança erros de sintaxe ou é interpretado localmente!

3

Eu tenho um comando como este que me diz se um sistema tem um disco cheio (> = 70% cheio):

if [[ -n df -PTh|column -t|awk '{print $6 $7}'|awk -F"%" '{printf "%-9s %-5s\n",$1,$2}'|grep -v -e "Use" -e "Mounted"|awk '$1>70{printf "%-9s %-5s\n",$1,$2}' ]]; then echo "not present"; else echo ">70 is present"; fi

Eu gostaria de querer executar o comando acima em um servidor remoto usando o SSH. Algo como:

ssh remoteserver "if [[ -n df -PTh|column -t|awk '{print $6 $7}'|awk -F"%" '{printf "%-9s %-5s\n",$1,$2}'|grep -v -e "Use" -e "Mounted"|awk '$1>70{printf "%-9s %-5s\n",$1,$2}' ]]; then echo "not present"; else echo ">70 is present"; fi"

Mas quando tentei isso, recebi o seguinte erro:

HOST: remoteserver bash: -c: line 0: syntax error in conditional expression bash: -c: line 0: syntax error near /home'
bash: -c: line 0:if [[ -n 92 /home'
    
por user275225 28.04.2014 / 07:49

1 resposta

8

Primeiro de tudo, eu reduziria o crime de guerra de uma declaração do awk / grep / awk / grep / awk / grep / etc para:

df | awk '$5~/([7-9]|10)[0-9]/'

Ele faz tudo que você precisa para verificar a saída. Você poderia adicionar uma cláusula {print ...} à instrução awk se você realmente necessitasse de uma boa saída, mas dado que você está apenas verificando se houver saída, ser razoável sobre isso.

Também podemos encurtar o if / else. Eu também corrigi a direção - a sua foi invertida. O comando inteiro agora parece:

[[ -n $(df | awk '$5~/([7-9]|10)[0-9]/') ]] && echo 'ACHTUNG!' || echo 'No >=70s'

Acho que você concorda que é apenas um pouco mais edificante.

Agora você provavelmente poderia escapar disso manualmente agora e envolvê-lo em um bash -c "..." , mas onde está a graça nisso? Em vez disso, vamos salvar o comando em um arquivo local (digamos commands.txt) para que você possa enviar para o servidor da seguinte forma:

ssh user@host $(<commands.txt)

E você poderia deixá-lo lá. Você poderia realmente lançar uma versão de trabalho do seu comando original lá e enviá-lo. Essa coisa é bem robusta ... Mas não queremos fazer isso ... Não quando podemos ser mais inteligentes (e baratos) com o comando e acabar com os colchetes if (que são as coisas que causam o problema de escape ).

No momento, estamos executando df remotamente e processando-a remotamente. Nós não precisamos fazer isso. Poderíamos deixar ssh executar df e depois manipular a saída localmente. Isso conserta instantaneamente o problema de escape, mas atualmente estamos amarrados na lógica [[ colchetes ]] , o que tornaria a reescrita um pouco feia:

[[ -n $(ssh user@host df | awk '$5~/([7-9]|10)[0-9]/') ]] && .......

Yuck.
Somos melhores que isso.
Ao contrário dos macacos e símios que pisaram antes de nós, temos códigos de saída.

Quando algo termina a execução, ele pode retornar um código. Esses códigos significam várias coisas , mas em geral 0 significa "Eu fiz exatamente o que fui projetado para fazer" e qualquer coisa maior significa "Eu fiz mal, Bawss".

Ganchos condicionais como && e || procuram o código de saída alimentando-os para decidir se devem ou não ser executados. Em nosso caso, isso significa que, se dissermos que awk sair de uma maneira diferente de zero, poderemos controlar o fluxo de código:

ssh user@host df | awk '$5~/([7-9]|10)[0-9]/ {exit 1}' && echo 'No >=70s' || echo 'ACHTUNG!'

Isso também significa que sairá assim que detectar o primeiro valor de > = 70. Se você tivesse milhões de unidades, isso poderia economizar segundos em relação a outros scripts de marcas líderes. Então, sim, apenas para reafirmar o que está acontecendo nesta versão final:

  1. Estamos nos conectando ao servidor e executando df remotamente
  2. A saída é redirecionada para uma instância local de awk
  3. awk procura ver se a quinta coluna corresponde a uma regex para corresponder a 70 a 100
  4. Em caso afirmativo, ele sai do código 1 e o código || é executado (existe é uma unidade com mais de 70% usada)
  5. Se não, sai o código 0 e o código && é executado.

Em revisões anteriores, eu também tinha uma verificação de NR>1 nas declarações awk , mas dado que estamos explicitamente verificando o valor da quinta coluna (e tem que ser um número para trabalhar), podemos omitir com segurança também.

    
por Oli 28.04.2014 / 12:52