
Eu tenho um script simples que executa comandos em um host remoto usando ssh
um 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 awk
remotamente 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 getHosts
array pode ser simplificado (raramente há uma razão para entrar grep
em 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
+ grep
em um único awk
comando. Também deixei o awk
comando 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 rsync
ou iasync
pertencente a um research
usuário.
É melhor fazer isso com pgrep
:
pgrep -l -U research 'rsync|iasync'
Para sinalizar esses processos, use pkill
no lugar de pgrep
e descarte a -l
opçã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ê xargs
suportar, isso pode ser feito para executar vários sh -c
processos ao mesmo tempo com -P n
, onde n
é o número de sh -c
comandos simultâneos que xargs
devem 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 "research
padrão "), elas devem ser escapadas com um \
, assim como os $
caracteres.