Estou tentando executar um conjunto de comandos em uma máquina remota, que inclui uma instrução if. Estou usando isso para encerrar uma lista de instâncias do KVM. A primeira linha deve ficar boa, mas poderia ser mais bonita, o resto precisa de ajuda.
ssh root@kvmsrv 'virsh shutdown $host 2> /dev/null; virsh destroy $host 2> /dev/null; sleep 2; virsh undefine $host 2> /dev/null'
# Also needs to be run on remote machine
# to disconnect iscsi
iscsiadm -m session | grep $host
if [ $? == 0 ]; then
iscsiadm -m node -T $stserver.$host -u
fi
# then on local machine
tid=`ssh root@storage1 'cat /proc/net/iet/volume' | grep $host | head -1 | awk '{print $1}' | awk -F: '{print $2}'`
if [ $tid ]; then
echo "Deleting tid:$tid from $stserver."
ssh root@$stserver "ietadm --op delete --tid=$tid"
fi
Acho que poderia fazer o mesmo com a segunda parte, apenas separar tudo com ; mas se alguém ler meu código mais tarde, provavelmente estará coçando a cabeça ...
Existe uma maneira de formatar tudo isso para que fique legível e ainda faça sentido e faça com que todos os comandos remotos sejam executados corretamente?
Responder1
Coloque sua longa e complexa sequência de comandos em seu próprio shell script, vamos chamá-lo
virsh-shutdown-remote.sh
Execute
ssh
e use o redirecionamento de entrada para executar o script:ssh root@kvmsrv < virsh-shutdown-remote.sh
Colocar os comandos em um script é uma boa ideia em qualquer caso.
Como dica extra, em vez disso:
iscsiadm -m session | grep $host if [ $? == 0 ]; then iscsiadm -m node -T $stserver.$host -u fi
Você pode escrever a mesma coisa de forma mais simples e curta em uma única linha:
iscsiadm -m session | grep $host && iscsiadm -m node -T $stserver.$host -u
Responder2
Você pode usar HEREDOCS
, por exemplo:
ssh root@kvmsrv <<EOF
virsh shutdown $host 2> /dev/null
virsh destroy $host 2> /dev/null
sleep 2
virsh undefine $host 2> /dev/null
# to disconnect iscsi
iscsiadm -m session | grep $host
if [ \$? == 0 ] ; then
iscsiadm -m node -T $stserver.$host -u
fi
EOF
Esteja ciente de que eu escapei, $?
caso contrário, seria avaliado pelo seu shell local e não pelo seu shell remoto. Como $host
parece estar definido localmente, você não precisará escapar disso.
Apenas um pequeno comentário, embora você não tenha solicitado. Você pode executar comandos virsh remotamente, sem a necessidade de fazer ssh explicitamente no host, por exemplo:
virsh -c qemu+ssh://root@kvmsrv/system destroy host
vai funcionar. Você também não precisa de ssh, pois o libvirt permite a autenticação com certificados SSL.
Responder3
Talvez apenas adicione comentários para explicar coisas que (deveriam ser) óbvias? Eu faço isso regularmente em roteiros para lembrar à minha própria bunda ignorante o que eu estava fazendo quando escrevi a coisa [censurada] em primeiro lugar.
Responder4
Bem, a resposta simples é que é realmente possível reescrever ssh root@kvmsrv 'cmd1; cmd2; cmd3'
como:
ssh root@kvmsrv '
cmd1
cmd2
cmd3
'
A única coisa a lembrar é que aspas simples "dentro" devem ser expressas como: '\''
. Exemplos:
ssh localhost '
echo hi
whoami
ls -ld /
var="'\''"
echo "$var"
if [ $? == 0 ]; then
echo "escaping single quote worked"
fi
'
# get single quote from file and print it
echo "'" > sqfile
ssh localhost '
#set -xv
echo hi
cat sqfile
var="$(cat sqfile)"
echo "$var"
'
# pass a single quote to the remote host and print it
# while keeping the outer single quotes for the ssh command
escsquote="'\''"
squote="'"
squote="'${squote//\'/${escsquote}}'" # bash
ssh localhost 'sh -c '\''
#set -xv
echo hi
echo "$1"
'\''' _ "$squote"