wget
herunterladenInhaltsverzeichnis
Mehrere Befehle ausführen lassen
Das Problem, das ich hier zu lösen versuche, ist das Problem der 20 Hände Ich muss auf einer großen Anzahl von VMs (Linux-Systemen) immer wieder dieselben oder zumindest sehr ähnliche Befehle ausführen. Das erfordert das Anmelden auf den ca. 20 VMs, das Eintippen der Befehle (mit den nicht ausbleibenden Fipptehlern) usw. Lässt sich das vereinfachen? Bestimmt, aber mit welchem Aufwand?
Grundsätzlich lassen sich alle Befehle scripten. Ich kann also für jede auszuführende Aktion ein Script verfassen und muss es dann auf dem Host ausführen lassen. OK. Und wie?
Weil meine Hosts alle auf ein gemeinsamens Filesystem zugreifen können1), kann ich so tun, als wäre das alles lokal. Das vereinfacht die Sache wesentlich. Nun muss ich nur noch ein Script schreiben, das nach Art eines Schedulers alle X Minuten2) nachsieht, ob etwas Neues abzuarbeiten ist.
Vom Aufbau her recht einfach:
- nachsehen, ob ein Anweisungsfile existiert
- wenn es da ist, einlesen (klar )
- in der Datei steht eine ID, die mit jeder neuen Dateiversion ansteigt
- in der Datei steht ein Array mit abzuarbeitenden Befehlen
- wenn die ID der Datei größer ist als die zuletzt bearbeitete ID: führe die Befehle aus
- schreibe die ID in eine Merkdatei für den nächsten Aufruf
Umgesetzt habe ich das mit Hilfe der Bash. Das Script sollte ab Bash Version 4 laufen3). Eine kleine Besonderheit ist noch drin: das Umkopieren des übergebenen Arrays CMDARR nach COMDAR. Wenn nämlich in der Befehlsdatei ein Index fehlen sollte, werden die Arrayelemente ordentlich nummeriert in den neuen Array geschrieben. Die Anzahl der Elemente bleibt, aber hinterher klappt auch die Schleife über die Arrayelemente
Und wer wissen will, warum ich hier nicht das gelegentlich beschriebene for COMD in ${CMDARR[*]}
(oder${CMDARR[@]}) benutze, mag es bitte mal selbst ausprobieren . Es ergibt sich dabei nämlich, dass jedes einzelne Wort von der FOR-Schleife als separates Element genommen wird (also jeder einzelne Befehl an den Leerzeichen aufgetrennt wird) *mööp*, setzen, 6
das Arbeitsscript
- workcmds.sh
#!/bin/bash ####################################### # # purpose of this script is to execute #+ various commands that are transmitted #+ in a separate file "$(basename $0 .sh).inc" #+ in the given order. #+ The number of commands will vary, #+ as will their nature ;-) # # written by w.flamme@web.de 2011-09-06 #+ with help from http://tldp.org/LDP/abs/html/ # will be needed ;-) PATH=/bin:/usr/bin:/sbin:/usr/sbin umask 002 # the array to hold the commands declare -a CMDARR # the file that will contain the array CONFILE="$(basename $0 .sh).inc" # the file that will contain the last executed command id LASTFILE="$(basename $0 .sh).last" # the command file has an id to identify the sequence LASTID=$(< "$LASTFILE") # this /must/ have a value... LASTID=${LASTID:-0} # if the file with the commands exists... if [ -f "$CONFILE" ]; then # ...read it... . "$CONFILE" # if CMDID is not set, assign a default value CMDID=${CMDID:-0} # if the read CMDID hasn't been processed yet... if [ $CMDID -gt $LASTID ]; then # how many commands do we have? NUMCMDS=${#CMDARR[@]} # if we have any, ... if [ $NUMCMDS -gt 0 ]; then # do someting with them COMDAR=(${CMDARR[*]}) for (( I = 0 ; I < $NUMCMDS ; I++ )) ; do # namely: execute them :-) "${!COMDAR[$I]}" done # for (( I = 0 ; I < $NUMCMDS ; I++ ) # note CMDID for later use echo $CMDID > "$LASTFILE" fi # if [ $NUMCMDS -gt 0 ] fi # [ $CMDID -gt $LASTID ] fi # if [ -f "$CONFILE" ]
Beispielbefehle
Die eingelesene Datei sieht dann etwa so aus:
- workcmds.inc
#!/bin/bash CMDID=3 CMDARR[0]="echo 'erster Befehl'" CMDARR[1]='echo ...und weiter...' CMDARR[2]="echo PATH=$PATH" CMDARR[3]="echo 'letzter Befehl'"
Sieht beherrschbar aus – mal sehen, wie es sich bewährt
Abwandlungen fallen mir schon ein:
- man schaut nicht nach einer Datei, sondern arbeitet alle Dateien in einem bestimmten Verzeichnis ab. Dazu müssten dann die Befehls-IDs in der Datei durch die Dateinamen ersetzt werden (eindeutig, steigend). Dann könnte man allerdings auch fertige Scripte direkt in das Verzeichnis einstellen…
- die erledigten Dateien des Verzeichnis' werden in einer Datei (deren Name den jeweiligen VM-Hostnamen enthält) gespeichert. Dadurch müssen die Dateinamen zwar noch eindeutig sein, aber nicht mehr aufsteigend.