Como evitar piping awk to awk?

3

Escrevi o seguinte script, que é executado a partir do crontab do meu usuário, encaminha ~/.ssh/config para a porta SSH e os conecta automaticamente se a linha Host terminar com "remoto", "local" ou " dinâmico. "

Exemplo ~/.ssh/config blocks:

Host localsocksdynamic
     DynamicForward 8080
     Hostname 1.2.3.4

Host localwebserverremote
     RemoteForward *:8080 localhost:80
     Hostname 1.2.3.4

Host indirectaccesslocal
     LocalForward 2222 2.3.4.5:80
     Hostname 1.2.3.4

Script:

#!/bin/sh

port_forwards=$(awk '/Host .*(remote|local|dynamic)/{printf $2} " "}' ~/.ssh/config  
for forward in ${port_forwards}
do
     port=$(awk "/${forward}/{f=1;next}/Host /{f=0}f" ~/.ssh/config | awk '/(Remote|Local|Dynamic)Forward/{print $2}' | cut -d':' -f2)
     [ -z ${port} ] || nc -z 127.0.0.1 ${port} || ssh -fqN ${forward} > /dev/null 2>&1
done

Funciona bem, mas eu queria saber se era possível combinar os comandos awk na linha port= para que não seja necessário canalizar um awk para outro. Depois de algumas horas de brincadeira e tentando entender a sintaxe, eu simplesmente não estou curtindo.

Eu sei que autossh existe e é uma maneira melhor de fazer o que estou fazendo, mas essa é uma experiência de aprendizado e tento realizar a mesma tarefa sem instalar um pacote.

    
por Q23 07.06.2017 / 23:11

1 resposta

3

Você pode realizar todo o processamento de texto com uma única invocação do AWK, simplificada, pois você só se importa com o encaminhamento:

#!/bin/sh

awk '/^Host / { host = $2 } host && /(Remote|Local|Dynamic)Forward/ { port=$2; gsub(".*:", "", port); print host, port }' ~/.ssh/config | while read host port; do
    nc -z 127.0.0.1 "${port}" || ssh -fqN "${host}" > /dev/null 2>&1
done

Escrito com mais legibilidade, o script AWK é

/^Host / { host = $2 }

host && /(Remote|Local|Dynamic)Forward/ {
    port=$2; gsub(".*:", "", port); print host, port
}

Isso armazena o host sempre que ele vê uma instrução "Host" e, em linhas encontradas enquanto um host válido é definido, e correspondendo a uma das instruções "Forward" aceitas, recupera a porta de destino, descarta a parte antes de dois pontos se any e gera o host e a porta:

localsocksdynamic 8080
localwebserverremote 8080
indirectaccesslocal 2222

Isso é então alimentado em um loop while read para verificar a porta e executar o SSH.

    
por 07.06.2017 / 23:31