Usar aqui-documento em uma linha?

Usar aqui-documento em uma linha?

Eu tenho um script simples que executa comandos em um host remoto usando sshum documento aqui.

Eu estava tentando fazer isso com uma linha na linha de comando, mas não consegui descobrir como fazer o documento aqui fora de um script. É possível? Passei algum tempo pesquisando e lendo documentação sobre documentos aqui, mas não me ocorreu.

Este script funciona bem - eu precisava da seção here-document para rodar awkremotamente via ssh, mas geralmente gosto de fazer one-liners para coisas simples:

#!/bin/bash
# it looks up all my hosts with 'db' in the name
# then gets the PID of any rsyncs running as user 'research'
# and pumps them into xargs

getHosts=(`curl --silent "http://assetts.lab/all_hosts" | grep -v ^# | awk -F" " '{print$1}'|grep db`)
for BOX in ${getHosts[@]};do
    echo "$BOX: "
    ssh -T sshUser@$BOX <<"EOF"
ps -ef | egrep "rsync|iasync" | awk -F" " '{if ($1 ~ "research") print $2}'|sudo xargs -i ps -fp '{}'
#ps -ef | egrep "rsync|iasync" | awk -F" " '{if ($1 ~ "research") print $2}'|sudo xargs -i kill '{}'
EOF
    echo
done

Provavelmente estou sentindo falta de algo simples... De qualquer forma, obrigado por qualquer sugestão :)

Responder1

Eu realmente não vejo necessidade de fazer nada sobre o uso de um documento aqui, mas eufazerveja que você pode simplificar um pouco outras coisas em seu script (o que, por sua vez, torna o documento aqui obsoleto).

Primeiro de tudo, o pipeline para preencher seu getHostsarray pode ser simplificado (raramente há uma razão para entrar grepem awk), e todo o array pode ser removido:

curl -s 'http://assetts.lab/all_hosts' |
awk -F ' ' '!/^#/ && $1 ~ /db/ { print $1 }' |
while IFS= read -r remote; do
   # rest of code
done

Aqui combinei seu comando grep+ awk+ grepem um único awkcomando. Também deixei o awkcomando alimentar os nomes de host diretamente no loop, em vez de armazená-los em uma variável intermediária.

Dentro do loop, parece que você deseja obter informações sobre um processo rsyncou iasyncpertencente a um researchusuário.

É melhor fazer isso com pgrep:

pgrep -l -U research 'rsync|iasync'

Para sinalizar esses processos, use pkillno lugar de pgrepe descarte a -lopção.

O script completo se torna:

#!/bin/sh

curl -s 'http://assetts.lab/all_hosts' |
awk -F ' ' '!/^#/ && $1 ~ /db/ { print $1 }' |
while IFS= read -r remote; do
   printf 'Processing host "%s"\n' "$remote"
   ssh "$remote" 'pgrep -l -U research "rsync|iasync"'
done

Ou, usando xargs:

#!/bin/sh

curl -s 'http://assetts.lab/all_hosts' |
awk -F ' ' '!/^#/ && $1 ~ /db/ { print $1 }' |
xargs -I {} sh -c '
   printf "Processing host \"%s\"\n" "$1"
   ssh "$1" "pgrep -l -U research \"rsync|iasync\""' sh {}

Se você xargssuportar, isso pode ser feito para executar vários sh -cprocessos ao mesmo tempo com -P n, onde né o número de sh -ccomandos simultâneos que xargsdevem continuar em execução.

Responder2

O recurso EOF bash é basicamente para ser usado como você faz no seu exemplo, ou seja, para enviar várias linhas de texto para outro comando.

Se você quiser isso como uma linha única, o EOF terá que ser eliminado.

Para executar um comando em um host remoto usando ssh, tudo que você precisa fazer é:

ssh host command

Por exemplo:

ssh host "ls -alh"

executará o comando no host e retornará a saída no console.

Seu código de exemplo pode ser reescrito em uma linha se você observar como usa as aspas, algo assim:

ssh host "ps -ef | egrep 'rsync|iasync' | awk -F' ' '{if (\$1 ~ \"research\") print \$2}'"

Essa string entre aspas duplas coloca os argumentos para comandos individuais entre aspas simples. Quando mais aspas duplas são necessárias (o "researchpadrão "), elas devem ser escapadas com um \, assim como os $caracteres.

informação relacionada