Estoy intentando ejecutar un conjunto de comandos en una máquina remota, que incluye una declaración if. Estoy usando esto para cerrar una lista de instancias de kvm. La primera línea debería estar bien, pero podría ser más bonita, el resto necesita ayuda.
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
Supongo que podría hacer lo mismo con la segunda parte, simplemente separarlo todo con ; pero si alguien va a leer mi código más adelante probablemente se estará rascando la cabeza...
¿Hay alguna manera de formatear todo esto para que sea legible y aún tenga sentido y que todos los comandos remotos se ejecuten correctamente?
Respuesta1
Coloque su larga y compleja secuencia de comandos en su propio script de shell, llamémoslo
virsh-shutdown-remote.sh
Ejecute
ssh
y utilice la redirección de entrada para ejecutar el script:ssh root@kvmsrv < virsh-shutdown-remote.sh
En cualquier caso, poner los comandos en un script es una buena idea.
Como consejo adicional, en lugar de esto:
iscsiadm -m session | grep $host if [ $? == 0 ]; then iscsiadm -m node -T $stserver.$host -u fi
Puedes escribir lo mismo de forma más sencilla y breve en una sola línea:
iscsiadm -m session | grep $host && iscsiadm -m node -T $stserver.$host -u
Respuesta2
Puedes usar HEREDOCS
, por ejemplo:
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
Tenga en cuenta que escapé, $?
de lo contrario, su shell local lo evaluaría y no desde su shell remoto. Como $host
parece estar definido localmente, no tendrás que escapar de él.
Sólo un pequeño comentario aunque no lo pediste. Puede ejecutar comandos virsh de forma remota, sin la necesidad de ingresar explícitamente mediante ssh al host, por ejemplo:
virsh -c qemu+ssh://root@kvmsrv/system destroy host
trabajará. Tampoco necesita ssh ya que libvirt le permite autenticarse con certificados SSL.
Respuesta3
¿Quizás simplemente agregar comentarios para explicar cosas que (deberían ser) obvias? Hago esto regularmente en los guiones para recordarle a mi ignorante trasero lo que estaba haciendo cuando escribí lo [censurado] en primer lugar.
Respuesta4
Bueno, la respuesta simple es que en realidad es posible reescribir ssh root@kvmsrv 'cmd1; cmd2; cmd3'
como:
ssh root@kvmsrv '
cmd1
cmd2
cmd3
'
Lo único que hay que recordar es que las comillas simples "dentro" de las comillas simples deben expresarse como: '\''
. Ejemplos:
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"