Ejecute la declaración if en una máquina remota

Ejecute la declaración if en una máquina remota

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

  1. Coloque su larga y compleja secuencia de comandos en su propio script de shell, llamémoslovirsh-shutdown-remote.sh

  2. Ejecute sshy 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 $hostparece 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"

información relacionada