Я пытаюсь запустить набор команд на удаленной машине, который включает оператор 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
Поместите вашу длинную и сложную последовательность команд в отдельный скрипт оболочки, назовем его
virsh-shutdown-remote.sh
Запустите
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"