Выполнить оператор if на удаленной машине

Выполнить оператор if на удаленной машине

Я пытаюсь запустить набор команд на удаленной машине, который включает оператор if. Я использую его для выключения списка экземпляров kvm. Первая строка должна быть хороша, но могла бы быть и красивее, остальное требует некоторой помощи.

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

Думаю, я мог бы сделать то же самое и для второй части, просто отделить все это с помощью ; но если кто-то позже прочтет мой код, он, вероятно, будет чесать голову...

Есть ли способ отформатировать все это так, чтобы это было читаемо и имело смысл, а все удаленные команды выполнялись правильно?

решение1

  1. Поместите вашу длинную и сложную последовательность команд в отдельный скрипт оболочки, назовем егоvirsh-shutdown-remote.sh

  2. Запустите sshи используйте перенаправление ввода для запуска скрипта:

    ssh root@kvmsrv < virsh-shutdown-remote.sh
    

В любом случае, размещение команд в скрипте — хорошая идея.

В качестве дополнительного совета, вместо этого:

iscsiadm -m session | grep $host
if [ $? == 0 ]; then
  iscsiadm -m node -T $stserver.$host -u
fi

То же самое можно написать проще и короче, в одну строку:

iscsiadm -m session | grep $host && iscsiadm -m node -T $stserver.$host -u

решение2

Вы можете использовать HEREDOCS, например:

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

Пожалуйста, учтите, что я экранировал $?, иначе это будет оценено вашей локальной оболочкой, а не удаленной. Поскольку это, $hostкажется, определено локально, вам не придется экранировать это.

Просто небольшой комментарий, хотя вы его не просили. Вы можете удаленно запускать команды virsh, без необходимости явного ssh-подключения к хосту, например:

virsh -c qemu+ssh://root@kvmsrv/system destroy host

будет работать. Вам также не нужен ssh, так как libvirt позволяет вам аутентифицироваться с помощью сертификатов ssl.

решение3

Может быть, просто добавить комментарий, чтобы объяснить вещи, которые (должны быть) очевидны? Я регулярно делаю это в сценариях, чтобы напомнить своей невежественной заднице, чем я занимался, когда писал [отцензуренную] вещь в первую очередь.

решение4

Ну, простой ответ заключается в том, что на самом деле это можно переписать ssh root@kvmsrv 'cmd1; cmd2; cmd3'так:

ssh root@kvmsrv '
cmd1
cmd2
cmd3
'

Единственное, что нужно помнить, это то, что одинарные кавычки «внутри» одинарных кавычек должны быть выражены как: '\''. Примеры:

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"

Связанный контент