Führen Sie die if-Anweisung auf dem Remotecomputer aus

Führen Sie die if-Anweisung auf dem Remotecomputer aus

Ich versuche, eine Reihe von Befehlen auf einem Remotecomputer auszuführen, die eine if-Anweisung enthalten. Ich verwende dies, um eine Liste von KVM-Instanzen herunterzufahren. Die erste Zeile sollte in Ordnung sein, könnte aber schöner sein, der Rest braucht etwas Hilfe.

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

Ich schätze, ich könnte dasselbe für den zweiten Teil tun, einfach alles mit ; ​​trennen, aber wenn jemand später meinen Code liest, würde er sich wahrscheinlich am Kopf kratzen ...

Gibt es eine Möglichkeit, dies alles so zu formatieren, dass es lesbar und weiterhin sinnvoll ist und alle Remote-Befehle ordnungsgemäß ausgeführt werden?

Antwort1

  1. Setzen Sie Ihre lange und komplexe Befehlsfolge in ein eigenes Shell-Skript, nennen wir esvirsh-shutdown-remote.sh

  2. Führen Sie sshdas Skript aus und verwenden Sie die Eingabeumleitung, um es auszuführen:

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

Es ist in jedem Fall sinnvoll, die Befehle in einem Skript unterzubringen.

Als zusätzlicher Tipp stattdessen:

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

Sie können dasselbe einfacher und kürzer in einer einzigen Zeile schreiben:

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

Antwort2

Sie können HEREDOCSbeispielsweise Folgendes verwenden:

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

Bitte beachten Sie, dass ich maskiert habe, $?da es sonst von Ihrer lokalen Shell und nicht von Ihrer Remote-Shell ausgewertet würde. Da es $hostlokal definiert zu sein scheint, müssen Sie es nicht maskieren.

Nur ein kleiner Kommentar, obwohl Sie nicht danach gefragt haben. Sie können Virsh-Befehle remote ausführen, ohne sich explizit per SSH beim Host anmelden zu müssen, z. B.:

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

wird funktionieren. Sie brauchen auch kein SSH, da Libvirt Ihnen stattdessen die Authentifizierung mit SSL-Zertifikaten ermöglicht.

Antwort3

Vielleicht einfach Kommentare hinzufügen, um Dinge zu erklären, die offensichtlich sein sollten? Ich mache das regelmäßig in Skripten, um meinen eigenen ignoranten Hintern daran zu erinnern, was ich vorhatte, als ich das [zensierte] Ding überhaupt geschrieben habe.

Antwort4

Die einfache Antwort lautet, dass es tatsächlich möglich ist, es wie folgt umzuschreiben ssh root@kvmsrv 'cmd1; cmd2; cmd3':

ssh root@kvmsrv '
cmd1
cmd2
cmd3
'

Das einzige, was Sie sich merken müssen, ist, dass einfache Anführungszeichen „innerhalb“ einfacher Anführungszeichen wie folgt ausgedrückt werden sollten: '\''. Beispiele:

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"

verwandte Informationen