4

I'm trying to run a set of commands on a remote machine, that includes an if statement. I'm using this to shutdown a list of kvm instances. The first line should be fine, but could be prettier, rest needs some help.

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 

I guess I could do the same for the second portion, just separate it all with ; but if anyone goes to read my code later on they'd probably be scratching their heads...

Is there a way to format all this so its readable and still makes sense and have all the remote commands execute properly?

4 Answers 4

4
  1. Put your long and complex sequence of commands in its own shell script, let's call it virsh-shutdown-remote.sh

  2. Run ssh and use input redirection to run the script:

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

Putting the commands in a script is a good idea in any case.

As an extra tip, instead of this:

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

You can write the same thing simpler and shorter on a single line:

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

You can use HEREDOCS, e.g:

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 

Please be aware that I escaped $? as otherwise it would be evaluated by your local shell and not from your remote shell. As $host seems to be defined locally you won't have to escape it.

Just a small comment though you didn't ask for it. You can remotely run virsh commands, without the need to explicitly ssh into the host, e.g:

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

will work. You also don't need ssh as libvirt allows you to authenticate with ssl certs insteads.

3
  • 1
    You forgot to escape his other variables, such as \$host, \$stserver. In fact it's better to write the whole thing as ssh root@kvmsrv <<"EOF" in which case you don't need to escape the $-s inside, and just use his script verbatim. Commented Jun 17, 2012 at 8:12
  • @janos as i said $host seems to be defined locally - the script never defines/get it somewhere. The same goes for $stserver. But i agree "EOF" is often better than escaping. Commented Jun 17, 2012 at 15:55
  • Notice that he single-quoted his very first command, so at least there $host is defined on the remote side. In the end he uses $host again in a local context, but it would be wrong to assume they are the same. As per his second block of code, from the context I think it's intended to run remotely, using variables defined on the remote, but I agree this is not at all 100% clear. Commented Jun 18, 2012 at 4:56
0

Maybe just add commentary to explain things that (should be) obvious? I do this regularly in scripts to remind my own ignorant butt what I was up to when I wrote the [censored] thing in the first place.

0

Well, the simple answer is that it is actually possible to rewrite ssh root@kvmsrv 'cmd1; cmd2; cmd3' as:

ssh root@kvmsrv ' cmd1 cmd2 cmd3 ' 

The only thing to remember is that single quotes "inside" single quotes should be expressed as: '\''. Examples:

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" 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.