awk na linha de comando ssh reclama 'nova linha inesperada ou fim da string' Como resolver?

4

Enquanto a execução do script abaixo teve um problema, ^ newline inesperado ou fim da string Como eu poderia resolver isso?

[root@emrbldbgdapd2 ~]# ./collectdata.sh
collect the data of 10.209.61.124
awk: cmd. line:1: {print
awk: cmd. line:1:       ^ unexpected newline or end of string
collect the data of 10.209.61.125
awk: cmd. line:1: {print
awk: cmd. line:1:       ^ unexpected newline or end of string
[root@emrbldbgdapd2 ~]#
==========
[root@emrbldbgdapd2 ~]# more collectdata.sh
for i in 'cat test'
do echo "collect the data of $i"
ssh -o LogLevel=error -o ConnectTimeout=5 $i 'hostname;
echo "############################";
free -g;
echo "######################################";
echo "######################################";
netstat -nr | grep [0-9] | tr [a-z] [A-Z];
echo "######################################";
echo "######################################";
mount|awk '{print $1,$3,$5}'|sort;
echo "######################################";
echo "######################################";
ip a s | grep -i eth*;
echo "######################################"'>output/$i-'date "+%d%b%Y"'
done
[root@emrbldbgdapd2 ~]#
    
por Levyle 30.01.2018 / 06:52

3 respostas

10

Você está tentando usar aspas simples em uma sequência de caracteres citada individualmente. A primeira cotação única interna, na mesma linha que o mount | awk | sort pipeline, encerrará a cotação única que é iniciada na linha ssh .

O erro real vem de awk . Ele recebe uma linha de comando parecida com {print ,,} (devido a $1 , $3 , $5 sendo expandida para strings vazias pelo shell de chamada e aspas simples estão ausentes neste ponto). Isso é interpretado como um programa awk com um erro de sintaxe (faltando } ) para ser executado em um arquivo chamado ,,} .

Eu recomendaria colocar o script em um arquivo de script real e executá-lo no host remoto, evitando problemas de cotação e permitindo que você crie um procedimento mais sustentável.

Além disso,

  1. Use read em while -loop em vez de fazer um for -loop sobre o resultado de cat .
  2. O script interno, em particular, carece de citações necessárias em vários lugares. Isto é necessário para que, e. grep [0-9] não acionará a globalização de nomes de arquivo.
  3. grep eth* parece estranho. Você quis dizer grep -e 'eth.' ? Além de agir como um padrão globbing de nome de arquivo que selecionaria qualquer nome no diretório atual que comece com eth , o padrão (se interpretado como uma expressão regular) corresponderia a et seguido por zero ou mais h . / li>
  4. Consulte Têm backticks (ou seja, 'cmd') shells in shuns foram depreciados? com relação ao uso de backticks.

Script modificado:

#!/bin/sh

now=$( date +%d%b%Y )

if [ -d output ]; then
    echo 'Output directory missing' >&2
    exit 1
fi

while read host; do
    printf 'Collecting data from "%s"...\n' "$host"

    ssh -n -o LogLevel=error -o ConnectTimeout=5 "$host" \
      sh <<'END_SCRIPT' >output/"$host-$now"
        echo '## HOSTNAME:'
        hostname
        echo '## FREE:'
        free -g
        echo '## NETSTAT:'
        netstat -nr | grep '[0-9]' | tr 'a-z' 'A-Z'
        echo '## MOUNT:'
        mount | awk '{ print $1, $3, $5 }' | sort
        echo '## IP:'
        ip a s | grep -i 'eth.*'
END_SCRIPT
done <hosts.txt
    
por 30.01.2018 / 07:40
5

Como mencionado em outras respostas, os problemas estão no uso de aspas simples no comando que você está executando no controle remoto. Como mostra a sintaxe colorida aqui no SE, o {print $1,$3,$5} não é citado e as aspas simples ao redor dele não alcançam o shell remoto.

Uma maneira de contornar isso seria enviar o script para o controle remoto através de stdin com um aqui-doc:

ssh somehost /bin/sh > outputfile <<"EOF"
hostname
free -g
netstat -nr | grep "[0-9]" | tr "[a-z]" "[A-Z]"
mount | awk '{print $1,$3,$5}' | sort
# and so on
EOF

Coloque o separador here-doc "EOF" entre aspas, para que as variáveis $1 não sejam expandidas pelo shell local. Isso deve cuidar dos problemas de citação com o shell local, mas você ainda precisa citar coisas para o controle remoto, como qualquer coisa que se pareça com um glob ( [0-9 e foo* ).

tr não precisa dos colchetes para os argumentos a-z (eles não fazem mal algum, eles apenas dizem para alterar um [ para um [ e o mesmo para ] ) . Embora eu ache que a saída desse netstat contenha os nomes da interface e, em maiúsculas, eles tornem os nomes diferentes.

    
por 30.01.2018 / 11:28
0

Altere a linha:

mount|awk '{print $1,$3,$5}'|sort;

Para:

mount|awk '\''{print $1,$3,$5}'\''|sort;
    
por 30.01.2018 / 07:01