Quantcast
Channel: Jochen Bauer Blog » computer
Viewing all articles
Browse latest Browse all 5

Überblick zur Shellskript-Programmierung

$
0
0

Arbeitet man mit Linux und will automatisch Programme starten und die Rückgaben weiterverarbeiten, dann bieten sich Shell-Skripte an. Hier will ich (vor allem für mich) bewährte Techniken festhalten und hochwertige Quellen für den Wiedereinstieg sammeln. Shellskripte sind im Endeffekt nichts anderes als das Arbeiten mit der Konsole.

Allgemeine Voraussetzungen

Der Name sollte beschreibend sein, aber es sollte nicht zu Konflikten zu Systembefehlen kommen, daher ist es geschickt ein Namenskürzel vorzuschalten, etwa joba_mysript.sh. Hilfreich ist es zu Beginn des Skripts die Eckdaten und die Optionen anzugeben – der Nutzer bekommt so schnell einen Überblick. Ich mache es so, dass ich zu Beginn die globalen Variablen bestücke, dann die Hauptprozedur als Funktion schreibe und unten im Skript dann noch die Skript-Start-Parameter abfrage. Das Skript kann so noch leicht um ein Textinterface erweitert werden. Wenn das Skript fertig ist, dann muss man nur noch die Datei via ‘chmod +x dateiname’ die Datei ausführbar machen und via ‘./dateiname’ in der Konsole ausführen. Zusätzlich kann man sich noch überlegen, ob man eine Log-Datei mitführt und was im Fehlerfall passiert.

Zu Beginn steht der Shebang ‘#!/bin/sh’, ja nach gewünschter Shell. Es folgt ein Skriptkopf mit Infos, dann die Variablen und die Funktion. Darunter die Hauptprozedur, die eine der Funktionen aufruft und so ins Skript verzweigt. Shellskripte sind unübersichtlich und anfällig für falsch gesetzte Leerzeichen. Ich händle es so, dass ich Variablen für den Skriptablauf in Großbuchstaben schreibe und Variablen für Skript-Verwaltungszwecke in Kleinbuchstaben, dafür aber mit meinem vorgestellten Namenskürzel, damit es mit Linux-Konsolenbefehlen keine Konflikte gibt.

Für die Konfiguration eines Shell-Skripts gibt es unter anderem folgende Möglichkeiten: man startet direkt mit der Prozedur und verlässt sich darauf, dass der Anwender in den Code blickt und dort die Konfiguration selbst vornimmt. Das ist wohl der Standardfall. Der nächste Schritt ist es dem Skript Startparameter zu ermöglichen. Diese werden abgefragt und die entsprechende Funktion aufgerufen. Will man den Anwender interaktiv die Sachen festlegen lassen, dann kann man in der Funktion den ‘read’-Befehl nutzen und die Nutzereingabe so lesen. Will man das Skript lange laufen lassen, dann kann man dem Nutzer ein Eingabemenü anbieten und je nach Wahl die Funktion für den Anwendungsfall aufrufen lassen. Dabei wird danach wieder das Eingabe-Menü angezeigt, bis der Nutzer das Skript beenden will – der Nutzer wird also in einer Schleife gefangen. Für Laien, die mit der Shell nicht umgehen wollen oder können, kann man das Skript mit ‘dialog’ aufpeppen und so hat man ein kleines Text-User-Interface.

Code-Schnippsel

Grundgerüst des Shellskripts


#!/bin/sh
#
# --- Infos -------------------------------------------------------------------
#
# Skriptname Shellskript-Gerüst
# Funktion TODO
#
# Beschreibung TODO
#
# benötigt keine externen Bibliotheken
#
# Autor Jochen Bauer
#
# Start 01.03.2011
# Stand 23.04.2011
# Version 1.0
#
# Fehler keine Fehler bekannt
# Kontakt info@jochen-bauer.net
#
# Beispielaufrufe (vorher mit 'chmod +x dateiname' ausführbar machen)
# Start mit Menue ./dateiname
# Start ohne Menue ./dateiname --noui
#
# Optionen
# --noui Konfiguration im Code übernehmen und starten
#
# --- Variablen ---------------------------------------------------------------
#
# $HOME # home-Ordner vom System
# $USER # user-Name vom System
$1 # Skript-Parameter
joba_error_file="" # Datei fuer Fehler-Ausgaben, optional
joba_error_var="" # Variablen fuer einen Fehler, optional
joba_log_file="" # Datei fuer Log-Datei, optional

# === Skriptparameter/Konfiguration ===
joba_working_dir=”/home/jay/Desktop/workingdir/”
joba_path_to_desktop=”/home/jay/Desktop/”

###############################################################################
# Koordination ohne Menueschleife
starteAnwendungOhneUi()
{
# voll im Code vorkonfigurierte Anwendung laufen lassen
echo “… voll vorkonfiguriert starten!”
}

###############################################################################
# Anwendungsfälle zur TextUI
starteBerechnung()
{
echo “\n … Anwendungsfall Start”
}

starteKonfiguration()
{
echo “\n … Anwendungsfall Konfiguration”
echo ” … absoluter Pfad zum Arbeitsverzeichnis:”
read joba_working_dir
echo ” … absoluten Pfad zum Desktop angeben:”
read joba_path_to_desktop
echo ” … Danke das war es, Anwendung konfiguriert!”
}

beendeAnwendung()
{
echo “\n … Anwendung planmaessig beendet!”
exit 0
}

###############################################################################
# TextUI-Hauptfunktion
zeigeHauptMenue()
{
joba_choice=”"
echo ” ”
echo ” ===================================”
echo ” | Menue [ Eingabe : Auswirkung; ] |”
echo ” | 1 : Start; 2 : Konfiguration; 0 : Beenden; ”
echo ” | —> Wahl: ”
read joba_choice

#######################################################################
# Anwendungsfaelle

# Start …
if [ "$joba_choice" = "1" ]
then
starteBerechnung
fi

# Konfiguration …
if [ "$joba_choice" = "2" ]
then
starteKonfiguration
fi

# Beenden
if [ "$joba_choice" = "0" ]
then
beendeAnwendung
fi
}

###############################################################################
# —————- main-Funktion … ————————————–
echo ” ”
echo ” ================================================”
echo ” | SHELL-SKRIPT ‘Titel’ |”
echo ” ================================================”
echo ” ”

# Skript-Parameter vorbelegen, abfragen, Anwendung starten, s. LinuxKUG S. 193
NOUI_FLAG=”false” # false: Ui anzeigen, Flag nicht genannt
for ARG in $@
do
#echo “Parameter-Aktuell: $ARG”
if [ "$ARG" = "--noui" ]
then
NOUI_FLAG=”true”
fi # Option-1/9
done

#echo “NOUI-Flag: $NOUI_FLAG”
if [ "$NOUI_FLAG" = "true" ] # UI nicht gewuenscht
then
#echo “Starte ohne TUI”
starteAnwendungOhneUi
else
#echo “Starte mit TUI”
while [ true ]
do
zeigeHauptMenue
done
fi
# exit-Codes
# exit 0 – Programm bewusst beendet, planmäßig abgelaufen
# exit 1 – Programm mit Fehler beendet
exit 0
# — Skript-Ende ————————————————————-

for-Schleife: Alle Dateien eines Verzeichnisses einlesen:

for DATEI in $(ls)
do
# Befehle pro Datei im aktuellen Verzeichnis, die mit ls gelistet wird
# ...
done

while-Schleife mit vorherigem Anlegen eines Arbeitsverzeichnisses mit Zeitstring:

# lege Arbeitsverzeichnis an
joba_time_day=`date +"%m-%d-%Y"`
joba_time_now=`date +"%T"`
joba_result_dir_name="einzelmsaberechnung-${joba_time_day}-${joba_time_now}/"
cd $joba_path_to_desktop
mkdir ${joba_result_dir_name}

# rufe das cpp-Programm auf
i=0;
while [ $i -le 100 ]
do
echo “Lauf-$i”
i=`expr $i + 1`
done

String konkatenieren und dabei Programmausgabe weiterverarbeiten und in Datei umleiten

# gehe Dateien ab
cd $joba_rawdata_dir
i=0
for joba_file_pointer in $( ls )
do
echo "Datei entdeckt: ${joba_file_pointer}"
# schreibe Eintrag als CSV-Eintrag
joba_temp1_string="$i;"
joba_temp2_string=`cat $joba_file_pointer`
joba_temp3_string=";"
joba_temp4_string=${joba_temp1_string}${joba_temp2_string}${joba_temp3_string}
echo "CSV-String: $joba_temp4_string"
echo ${joba_temp4_string} >> ${joba_path_to_output_dir}${joba_output_filename}
i=`expr $i + 1`
done

Hilfreiche Quellen und Links

Ubuntuusers-Einstieg: http://wiki.ubuntuusers.de/shell
Bash-Scripting-Guide: http://tldp.org/LDP/abs/html/
Linux-Shell-Scripting-Tutorial: http://www.freeos.com/guides/lsst/
Linux-Shell-10-Seconds-Guide: http://linuxhelp.blogspot.com/2005/10/10-seconds-guide-to-bash-shell.html
Wikibook: http://de.wikibooks.org/wiki/Linux-Kompendium:_Shellprogrammierung

Link zur Textdatei der Vorlage: joba-shellskript-vorlage.sh


Viewing all articles
Browse latest Browse all 5

Latest Images

Trending Articles





Latest Images