Ich habe diesen Code:
#!/bin/sh
echo "--------- Backup config files -------------"
find /vmfs/volumes/datastore1/ \
-type f \
-regex '.*\.\(vmx\|nvram\|vmsd\|vmdk\)$' \
! -name '*-flat.vmdk' \
-exec sh -c "$(cat << 'EOF'
addrs=XX.XX.XX.XX
for pth; do
drctry="$(printf '%s' "${pth%/*}" | sed "s/'/'\"'\"'/g")"
ssh "root@$addrs" "mkdir -p '$drctry'" && scp -pr "$pth" "$addrs:'$drctry/'"
done
EOF
)" sh {} +
echo "----------- Backup VM disks ---------------"
vim-cmd vmsvc/getallvms | sed -e '1d' -e 's/ \[.*$//' | while read -r line; do
addrs=XX.XX.XX.XX
vmid="$(printf '%s' "${line%}" | awk '{print $1;}'| sed "s/'/'\"'\"'/g")"
vmname="$(printf '%s' "${line%}" | awk '{for (i=2; i<=NF; i++) print $i}'| sed "s/'/'\"'\"'/g")"
vim-cmd vmsvc/snapshot.create $vmid backup 'Snapshot created by Backup Script' 0 0
scp -pr "/vmfs/volumes/datastore1/$vmname/$vmname-flat.vmdk" $addrs:"/vmfs/volumes/datastore1/$vmname"
vim-cmd vmsvc/snapshot.removeall $vmid
done
Der erste Teil (Sicherungskonfigurationsdateien) funktioniert einwandfrei. Der zweite Teil (Sicherungs-VM-Festplatten) nicht. Die Ausgabe der vim-cmd-Zeile (die die Schleife startet) lautet:
1 VM_1
10 VM_2 with_space
11 VM_3 with space
12 VM_4 with_space
14 VM_5
Ich muss:
- Weisen Sie der Variable $vmid das erste Wort (die numerische ID) zu.
- Weisen Sie den Rest der Wörter der Variable $vmname zu, damit ich den Pfad für den SCP-Befehl verketten und ihn erfolgreich ausführen kann, ohne auf Probleme zu stoßen, die durch Leerzeichen im Verzeichnisnamen und im Dateinamen verursacht werden
Derzeit erhalte ich Erfolg für alle VMs, deren Name kein Leerzeichen enthält. Für die anderen erhalte ich:
Create Snapshot:
/vmfs/volumes/datastore1/VM_name
with_space/VM_name
with_space.vmdk: No such file or directory
sh: with_space: not found
Remove All Snapshots:
UPDATE 1: Für diejenigen, die die Ausgabe von „vim-cmd vmsvc/getallvm s“ wissen müssen, hier ist sie:
Vmid Name File Guest OS Version Annotation
1 VM_1 [datastore1] VM_1/VM_1.vmx winXPProGuest vmx-13
10 VM_2 with_space [datastore1] VM_2 with_space/VM_2 with_space.vmx opensuse64Guest vmx-13
11 VM_3 with space [datastore1] VM_3 with space/VM_3 with space.vmx opensuse64Guest vmx-13
12 VM_4 with_space [datastore1] VM_4 with_space/VM_4 with_space.vmx opensuse64Guest vmx-13
14 VM_5 [datastore1] VM_5/VM_5.vmx winXPProGuest vmx-13
UPDATE 2:
Dank @Sorin konnte ich dieses Monster um mehr als 60 % auf 8 Zeilen reduzieren. Dies ist also die Klonlösung für Arme, die einen kostenlosen ESXi 6.5-Host auf einen anderen Host klonen:
#!/bin/sh
addrs=XXX.XXX.XXX.XXX
IFS="\t" vim-cmd vmsvc/getallvms | sed -e '1d' -e 's/ \[.*//g' -e "s/\s\+/\t/" | while read id name; do
echo "----- Backup "$name" --------"
scp -pr "/vmfs/volumes/datastore1/$name/$name.vmx" "/vmfs/volumes/datastore1/$name/$name.nvram" "/vmfs/volumes/datastore1/$name/$name.vmsd" "/vmfs/volumes/datastore1/$name/$name.vmdk" $addrs:"'/vmfs/volumes/datastore1/$name'"
vim-cmd vmsvc/snapshot.create $id backup 'Snapshot created by Backup Script' 0 0
scp -pr "/vmfs/volumes/datastore1/$name/$name-flat.vmdk" $addrs:"'/vmfs/volumes/datastore1/$name'"
vim-cmd vmsvc/snapshot.removeall $id
done
Danke !!
Antwort1
Sie können die erste Gruppe von Leerzeichen durch einen Tabulator ersetzen, das IFS auf „\t“ setzen und sowohl die ID als auch den Namen mit „read“ auslesen, etwa so:
IFS="\t" cat test | sed -e '1d' -e 's/ \[.*//g' -e "s/\s\+/\t/" |\
while read id name; do echo -e "id:$id\nname:$name";done
id:1
name:VM_1
id:10
name:VM_2 with_space
id:11
name:VM_3 with space
id:12
name:VM_4 with_space
id:14
name:VM_5
Aufgrund der Ausgabe, die Sie von getallvms erhalten, halte ich das jedoch nicht für sicher. Die Ausgabe scheint eine feste Breite zu haben, aber es ist nicht klar, ob diese Breite gleich ist oder von der Länge des VM-Namens abhängt oder ob der Name abgeschnitten wird, wenn er zu lang ist. Ich habe nach einem Handbuch für vim-cmd gesucht, um zu sehen, ob Sie das Format steuern können, aber es gibt online keine Dokumentation, die Befehlszeilenoptionen abdeckt. Überprüfen Sie, ob vim-cmd Optionen zur Steuerung der Ausgabe hat (vielleicht können Sie ein explizites Trennzeichen für die Spalten festlegen oder es kann XML/JSON exportieren ...)
Wenn dies nicht möglich ist, schlage ich vor, nur die virtuelle Mid von getallvms abzurufen und zu verwenden, vim-cmd vmsvc/get.summary $vmid
um den Namen abzurufen.
Um Ihnen den genauen Code zu geben, bräuchte ich ein Beispiel der get.summary-Ausgabe, aber im Großen und Ganzen würde er so aussehen:
vim-cmd vmsvc/getallvms | sed -e '1d' | awk "{print $1} | while read id; do
vmname=$(vim-cmd vmsvc/get.summary $vmid | \
sed '/ guest =/,/}/d' | egrep name | sed 's/.*= //;s/,//;s/ *$//')
...
done
Dies wurde nicht getestet. Das meiste davon habe ich von:http://unixetc.co.uk/2015/03/28/list-virtual-machines-on-esxi/
Ah, jetzt sehe ich, dass Ihr Problem eigentlich der SCP-Befehl ist. Remote-SCP-Adressen müssen doppelt maskiert werden. Versuchen Sie:
scp -pr "/vmfs/volumes/datastore1/$vmname/$vmname-flat.vmdk" $addrs:"'/vmfs/volumes/datastore1/$vmname'"
Oder wenn Sie Bash haben, können Sie printf verwenden, um den Dateinamen in Anführungszeichen zu setzen:
SRC=$(printf /vmfs/volumes/datastore1/%q/%q-flat.vmdk "$VMNAME" "$VMNAME")
DEST=$(printf %s:'/vmfs/volumes/datastore1/%q' $addr "$VMNAME")
und verwenden Sie das in Ihren SCP-Befehlen
Antwort2
Vielleicht ist es nicht relevant, aber mit Perl ist es recht einfach zu erreichen.
Gegeben: test.out:
Vmid Name File Guest OS Version Annotation
1 VM_1 [datastore1] VM_1/VM_1.vmx winXPProGuest vmx-13
10 VM_2 with_space [datastore1] VM_2 with_space/VM_2 with_space.vmx opensuse64Guest vmx-13
11 VM_3 with space [datastore1] VM_3 with space/VM_3 with space.vmx opensuse64Guest vmx-13
12 VM_4 with_space [datastore1] VM_4 with_space/VM_4 with_space.vmx opensuse64Guest vmx-13
14 VM_5 [datastore1] VM_5/VM_5.vmx winXPProGuest vmx-13
Die Aufgabe wird mit der folgenden Befehlszeile erledigt:
$ cat test.out |perl -ne 'if (/(\d+)[ \t]*([^[]+)/) { print "id is $1, name is $2\n"; }'
id is 1, name is VM_1
id is 10, name is VM_2 with_space
id is 11, name is VM_3 with space
id is 12, name is VM_4 with_space
id is 14, name is VM_5
Sie können die Ausgabe von Perl problemlos anpassen, um sie mit der Shell besser nutzbar zu machen ...
NOTIZ: Dieser Einzeiler merkt sich den Namen, bis die Zeichenfolge „[datastore]“ erreicht wird. Wenn die Dateispalte von „[datastore]“ abweicht, wird das Skript beschädigt …