linux + ssh + executa duas tarefas em um ssh e imprime em CSV

2

o seguinte comando imprime os dois valores em um ssh shut

ssh test01 "hostname && cat  /etc/sysconfig/rhn/rhnsd "


test01
INTERVAL=240

mas como alterar a sintaxe para imprimir o seguinte formato: (CSV),

 test01,INTERVAL=240

.

Eu tento (mas não como esperado)

ssh test01 "hostname && cat  /etc/sysconfig/rhn/rhnsd " | awk '{print $1","$2}'


test01,
INTERVAL=240,
    
por yael 03.05.2016 / 17:09

3 respostas

2

Tudo o que você precisa fazer é analisar a saída do comando e substituir a primeira nova linha ( \n ) por uma vírgula. Isso deve funcionar:

ssh test01 "hostname && cat  /etc/sysconfig/rhn/rhnsd " | 
    perl -00pe 's/\n/,/'

Aqui, estamos usando perl para introduzir o arquivo inteiro na memória ( -0 ) e substituir o primeiro \n por vírgula. O -p informa perl para imprimir cada "linha" de entrada (aqui, uma linha é o arquivo inteiro) depois de executar o script fornecido por -e sobre ele.

O motivo pelo qual awk não funcionou é porque awk executa o script que você fornece em todas as linhas. Seu comando imprime duas linhas, as quais possuem apenas um único campo, $1 , portanto, $2 é indefinido. Portanto, print $1","$2 é expandido para print "test01""," para a primeira linha e print "INTERVAL=240""," para a segunda, resultando em

test01,
INTERVAL=240,

Uma solução de trabalho com awk seria:

ssh test01 "hostname && cat  /etc/sysconfig/rhn/rhnsd " | 
    awk '{printf "%s,", $1}' | sed 's/,$//'

Isso imprimirá o primeiro campo de cada linha seguido por uma vírgula. O comando sed apenas remove a vírgula final após a última linha impressa.

Para imprimir a linha inteira em vez de apenas um campo, use:

ssh test01 "hostname && cat  /etc/sysconfig/rhn/rhnsd " | 
    awk '{printf "%s,", $0}' | sed 's/,$//'
    
por 03.05.2016 / 17:48
1

Seguindo o conselho do terdon , estou adicionando uma abordagem alternativa usando sed , principalmente incluí-lo para completude, no entanto, ao contrário do awk '{printf "%s,", $1}' que agrega enquanto omitir a nova linha , com sed estamos ativamente substituindo as novas linhas , assim também se encaixaria quando quiséssemos substituir um caractere diferente. É ineficiente embora.

O comando em questão é ssh test01 "date +%m && hostname && cat asdfd.txt && date +%D" | sed ':a;N;s/\n/, /;ba'

O comando muito críptico sed :a;N;s/\n/, /;ba é realmente bastante simples se desmontado.

sed transforma a entrada em uma única passagem (em oposição a, por exemplo, ed , mas ed geralmente não é incluído por padrão). O comando ssh não modificado retorna:

[me@hostname ~]$ ssh test01 "date +%m && hostname && cat asdfd.txt && date +%D"
05
Debian-76-wheezy-64-minimal
a
s
d
f
d
05/04/16

Se adicionarmos N;s/\n// , obtemos:

[me@hostname ~]$ ssh test01 "date +%m && hostname && cat asdfd.txt && date +%D" | sed 'N;s/\n//'
05Debian-76-wheezy-64-minimal
as
df
d05/04/16

O N acrescenta a linha de entrada próximo no espaço padrão, o seguinte s/\n// remove a nova linha no espaço padrão. É por isso que recebemos pares de linhas com novas linhas removidas aqui

Agora, se quisermos que a entrada completa seja enviada para o espaço de padrão, precisamos loop com a ajuda de um rótulo.

[me@hostname ~]$ ssh test01 "date +%m && hostname && cat asdfd.txt && date +%D" | sed ':a;N;s/\n//;ba'
05Debian-76-wheezy-64-minimalasdfd05/04/16

Com :a , definimos um rótulo, com ba saltamos incondicionalmente para o rótulo a .

Então, o que sed ':a;N;s/\n//;ba' faz é:

  • Definir rótulo a
  • Anexar a próxima linha ao espaço padrão ( N )
  • Enviar espaço padrão por meio de s/\n//
  • Volte para a

Quando não houver uma nova linha para N anexá-la ao final do script.

Para obtê-lo, precisamos apenas alterar a substituição:

[me@hostname ~]$ ssh test01 "date +%m && hostname && cat asdfd.txt && date +%D" | sed ':a;N;s/\n/, /;ba'
05, Debian-76-wheezy-64-minimal, a, s, d, f, d, 05/04/16

Isso não é muito eficiente, especialmente para maior número de linhas, já que o espaço de padrão recebe a linha anexada e enviada através de nosso comando de substituição para cada linha. Seria mais eficiente substituir antes da agregação, mas sed não pode fazer isso.

Isso se torna muito óbvio se imprimirmos o espaço de padrão após N anexar a próxima linha (Basta colocar um p na posição para obter o espaço de padrão atual impresso).  Na saída seguinte, cada 2 linhas representam o espaço de padrão atual (porque a * nova linha ainda está incluída) - pouco antes da substituição da nova linha por s/\n// :

[me@hostname] ssh test01 "date +%m && hostname && cat asdfd.txt && date +%D" | sed ':a;N;p;s/\n/, /;ba'
05
Debian-76-wheezy-64-minimal
05, Debian-76-wheezy-64-minimal
a
05, Debian-76-wheezy-64-minimal, a
s
05, Debian-76-wheezy-64-minimal, a, s
d
05, Debian-76-wheezy-64-minimal, a, s, d
f
05, Debian-76-wheezy-64-minimal, a, s, d, f
d
05, Debian-76-wheezy-64-minimal, a, s, d, f, d
05/04/16
05, Debian-76-wheezy-64-minimal, a, s, d, f, d, 05/04/16
    
por 04.05.2016 / 01:23
0

Para o seu comando, isso produziria a saída esperada:

counter=0
ssh test01 "hostname && cat  /etc/sysconfig/rhn/rhnsd " \
  | while read line ; do 
  ((counter++)) 
  if [[ counter -eq 1 ]]; then 
    echo -ne "${line},"
  else
    echo "$line"
  fi
  done
    
por 03.05.2016 / 17:45