5.1 Basics

Inhalt

Scripts

Was ist ein Script?

Scripts sind kleine Programme, welche ein Set von Anweisungen sequenziell ausführen. Im Unterschied zu kompilierten Programmen (z.B. vi oder einer Smartphone App), werden Scripts zur Laufzeit interpretiert und müssen nicht vorgängig in Maschinencode umgewandelt (kompiliert) werden. Das erleichtert den Umgang mit solchen Scripts, da sich deren Programmcode mit einem einfachen Texteditor anschauen und verändern lässt. Scripts lassen sich grundsätzlich in jeder interpretierten Programmiersprache (also einer, deren Programmcode vor der Ausführung nicht kompiliert werden muss) schreiben. Im Systemengineering Umfeld trifft man meist auf Python oder Bash Scripts. Aus diesem Grund beschränken wir uns in diesem Lab auf die zwei erwähnten Sprachen.

Wozu verwendet man ein Script

Scripts kommen überall da zur Anwendung, wo bestimmte Arbeitsabläufe automatisiert werden sollen. Ein Script kann z.B. verwendet werden, um eine Sicherung (Backup) von Dateien zu erstellen. Der Ablauf eine solchen Scripts könnte z.B. wie folgt aussehen:

  1. Erstellen eines Archives (z.B. tar.gz oder zip) von einem oder mehreren Ordnern
  2. Kopieren dieses Archives auf einen Server oder eine externe Festplatte
  3. Senden eines Mails mit dem Status des Backups

Anstatt diese drei Schritte jeweils von Hand auszuführen, lassen sich diese in einem Script zusammenfassen. Anschliessend lässt sich das Backup mit einem einzigen Befehl (ausführen des Scripts) erstellen. Weitere Beispiele von Scripts finden sich z.B. im ansible-puzzle Repository (suche nach .sh)

Bash vs. Python

Wenn man ein Script erstellen möchte, stellt sich als Erstes die Frage, in welcher Programmiersprache ein solches Script geschrieben werden soll. Meist liegt es nahe, ein Script in Bash zu erstellen, z.B. weil man die nötigen Befehle bereits kennt und evtl. auch bereits in der richtigen Reihenfolge von Hand ausgeführt wurden und nun nur noch in ein Script zusammengefasst werden müssen. Für einfache/kurze Scripts (wie z.B. das oben erwähnte Backup Script) spricht grundsätzlich nichts gegen ein Bash Script. Du solltest jedoch bedenken, dass komplexere Aufgaben (viele Kontrollstrukturen, Error handling etc.) in einem Bash Script nur schwer abzubilden sind. Für komplexere Aufgaben oder längere (ca. 100 Zeilen oder mehr) Script solltest du also von Anfang an zu Python greifen.

Lesbarkeit

Egal in welcher Sprache du dein Script erstellst, du solltest immer auf eine gute Lesbarkeit des Scripts achten. Dazu solltest du folgende Punkte berücksichtigen:

  1. Keep it simple: schreibe den Code so einfach wie möglich und so komplex wie nötig
  2. Verwende sprechende Variablen- und Funktionsnamen (z.B. message anstatt m oder addition() statt a())
  3. Achte auf die korrekte Einrückung des Codes
  4. Verwende jeweils lange Parameter statt die abgekürzte Version (rm --force --recursive statt rm -fr)
  5. Lagere mehrmals verwendeten Code in eine Funktion aus (mehr dazu im Kapitel 5)

Shebang

Als Shebang wird eine Zeichenfolge bezeichnet, welche dem Computer angibt, mit welchem Interpreter ein Script ausgeführt wird. Der Shebang besteht aus der Zeichenfolge #! gefolgt vom Pfad zum Interpreter (z.B. #!/usr/bin/python). Um ein Script möglichst auf allen Systemen lauffähig zu machen, hat es sich bewährt, anstelle des Interpreters (in diesem Fall /usr/bin/python) /bin/env gefolgt vom gewünschten Interpreter (z.B. python) zu verwenden: #!/bin/env python. Dadurch ist das Script auch auf Systemen lauffähig, bei welchen Python nicht unter /usr/bin/ installiert wurde. Der Shebang muss jeweils zu oberst im Script angegeben werden:

Bash

cat /usr/local/scripts/example
#!/bin/env bash
...

Python

cat /usr/local/scripts/example
#!/bin/env python
...

Damit das Script direkt (ohne Angabe des Interpreters) lauffähig wird, müssen die Berechtigungen entsprechend gesetzt werden:

1
chmod +x /usr/local/scripts/example

Kommentare

Beschreibe deinen Code mit Kommentaren! Dies hilft nicht nur den Anderen beim Review des Scripts, sondern auch dir selbst, wenn du den Code ein paar Wochen / Monate später wieder ändern/verstehen musst.

Weitere Information zu Clean Code practices findest du unter:

Docstrings

Neben den klassischen Kommentaren existieren in Python noch sogenannte Docstrings. Docstrings sind Texte, welche die Funktionsweise einer bestimmten Funktion und/oder des Scripts beschreiben. Der Module Docstring existiert einmalig am Anfang des Scripts und beschreibt, wozu das Script verwendet wird:

1
2
3
4
#!/bin/env python
""" This script prints the text "Hello World!""""

print("Hello world!")

Wie du am Beispiel oben siehst, definierst du den Module Docstring, indem du den gewünschten Text in drei Anführungszeichen einfasst.

Python imports

Wenn du Python startest, stehen dir viele eingebaute Funktionen (mehr dazu später im Kapitel 5) automatisch zur Verfügung. So kannst du z.B. mit der Funktion len() die Länge eines Objektes ermitteln. Andere Funktionen welche z.B. zum Löschen einer Datei erforderlich sind, stehen nicht automatisch zur Verfügung. Diese Funktionen sind in eigenen Python Modulen abgekapselt. Um die Funktionen in deinem Script verwenden zu können, musst du die passenden Module zuerst laden. Dazu wird die import Funktion verwendet. Beispiel:

1
2
import os
os.remove("/pfad/zur/datei")

In der ersten Zeile dieses Beispieles importieren wir alle Funktionen des os Moduls. Auf der zweiten Zeile führen wir anschliessend die remove() Funktion des os Moduls aus. Aus Performancegründen kann es sinnvoll sein, nur die effektiv verwendeten Funktionen eines Moduls zu laden. Dazu wird folgende Syntax verwendet:

1
2
from os import remove
remove("/pfad/zur/datei")

Da wir in diesem Beispiel explizit die remove() Funktion laden, müssen wir diese bei deren Verwendung nicht mehr mit dem Modulname prefixen. Anstelle von os.remove() schreiben wir daher nur remove().

Imports sind nicht nur für die von Python standardmässig mitgelieferten Module (wie z.B. os) möglich, sondern auch für selbst geschriebene Programme. Wenn dein Programm über sehr viele Funktionen verfügt, kannst du diese in eine separate Datei auslagern und diese anschliessend im Hauptscript importieren. Wie genau das funktioniert, ist für dieses Lab nicht relevant. Du findest aber unter folgenden Links weitere Informationen zum Thema:

Struktur

In Python Scripts wirst du immer wieder folgende Struktur antreffen:

1
2
3
4
5
6
def main():
	print('Hello World')


if __name__ == "__main__":
    main()

Damit legen wir fest, dass wir beim Aufrufen eines Scripts die Funktion main() aufrufen wollen. Das soll dazu dienen, dass der Programmcode nur beim expliziten Starten des Scripts (z.B. über python /pfad/zum/script.py), nicht jedoch bei einem import ausgeführt wird.