リモートマシンで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

2 番目の部分についても同じように、単にすべてを ; で区切るだけでよいと思いますが、後で誰かが私のコードを読むと、おそらく頭を悩ませることになると思います...

これをすべて読みやすく、意味を成し、すべてのリモート コマンドが適切に実行されるようにフォーマットする方法はありますか?

答え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

同じことを 1 行でよりシンプルかつ短く書くこともできます。

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ローカルで定義されているようなので、エスケープする必要はありません。

求められてはいませんが、ちょっとしたコメントです。ホストに明示的に ssh する必要なく、virsh コマンドをリモートで実行できます。例:

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

動作します。libvirt では SSL 証明書による認証が可能なため、SSH も必要ありません。

答え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"

関連情報