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
Setzen Sie Ihre lange und komplexe Befehlsfolge in ein eigenes Shell-Skript, nennen wir es
virsh-shutdown-remote.sh
Führen Sie
ssh
das 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 HEREDOCS
beispielsweise 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 $host
lokal 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"