我正在尝试在远程计算机上运行一组命令,其中包括 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
将你的又长又复杂的命令序列放在它自己的 shell 脚本中,我们称之为
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
请注意,我转义了$?
,否则它将由您的本地 shell 进行评估,而不是从远程 shell 进行评估。正如$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"