8 Scripting und Systemadministration
Es gibt wenige Bereiche des Codings, bei denen die KI-Unterstützung – richtig eingesetzt! – so gut funktioniert wie beim Scripting mit Python und der Bash. Dabei spielt die Natur von Scripts eine Rolle: Oft reichen relativ wenige Zeilen Code zur Erledigung einer klar definierten Aufgabe. Während der Code bei großen Programmierprojekten über Dutzende, oft Hunderte von Dateien verteilt ist, kann ein Script oft in einer einzigen Datei formuliert werden. Dementsprechend gibt es kaum Abhängigkeiten und Kontextprobleme, die KI-Sprachmodelle überfordern.
Eigentlich hatten wir erwartet, beim Scripting unter Windows mit der PowerShell ähnlich gute Erfahrungen zu machen. Diesbezüglich wurden wir aber enttäuscht. Das bei unseren Tests bevorzugt eingesetzte Modell GPT 4o lieferte (Stand: Mitte 2024) qualitativ wesentlich schlechteren Code mit deutlich mehr Fehlern. Natürlich gibt es zur PowerShell im Internet weniger Trainingsmaterial als für Python, aber dass der Unterschied so offensichtlich sein würde, war doch überraschend.
Dessen ungeachtet präsentieren wir Ihnen in diesem Kapitel eine ganze Sammlung von Beispielen, wo uns ChatGPT, GitHub Copilot und andere KI-Tools geholfen haben. Unser Ziel ist einmal mehr, Ihnen eine breite Palette von Anwendungsmöglichkeiten zu präsentieren. Vielleicht ist die eine oder andere Idee dabei, an die Sie noch nicht gedacht haben?
Darüber hinaus sehen wir in diesem Kapitel ein wenig über den Scripting-Tellerrand hinaus und gehen auch auf Nebenthemen wie reguläre Ausdrücke und Systemadministration ein.
Nun ist die Systemadministration eigentlich kein klassisches Coding-Thema und liegt daher außerhalb des Schwerpunkts dieses Buchs. Aber in der Praxis sind viele Entwickler und Programmiererinnen auch für das Set-up von Docker-Containern, Git-Repositorys, Datenbanksystemen und Servern zuständig. ChatGPT und Co. sind absolut in der Lage, dabei zu helfen.
8.1 Scripting
Die aus unserer Sicht ideale Arbeitsumgebung zum Verfassen neuer Scripts ist ein Editor mit KI-Unterstützung (z. B. VS Code plus GitHub Copilot) sowie ein eigenes Chat-Fenster – egal, ob als Teilfenster des Editors oder davon losgelöst in einem Webbrowser. Der KI-Chat hilft beim prinzipiellen Entwurf von Teilen des Scripts sowie bei der Recherche der eingesetzten Kommandos, CmdLets oder Module. Der Editor unterstützt die Code-Eingabe, die Dokumentation und das Debugging. Die folgenden Seiten präsentieren einen bunten Mix von Beispielen.
Bash: Schleife über eine Textdatei
Sie wollen in einem Bash-Script eine Textdatei verarbeiten und dabei die erste Zeile mit der Spaltenbeschriftung überspringen. Was ist der einfachste Weg? Sie fragen ein KI-Tool!
Prompt: bash: I want to loop over all lines of file but skip the first line.
In Bash, if you want to loop over all lines of a file but skip the first line, you can use the following script:
# Assuming 'file.txt' is your file
tail -n +2 file.txt | while IFS= read -r line
do
echo "$line"
done
Here’s a breakdown of the script (more details …)
ChatGPT liefert eine ebenso kurze wie optimale Lösung. Die eher langatmigen Erläuterungen zum Script sind primär für Bash-Einsteiger interessant.
PowerShell: Fotos sortieren
Sie möchten mit einem PowerShell-Script die EXIF-Daten einer ganzen Sammlung von Fotos auswerten. Die Bilddateien sollen entsprechend in Verzeichnisse der Form yyyy-mm verschoben werden, also z. B. 2024-06 für im Juni 2024 entstandene Fotos.
Prompt: PowerShell script: I have a lot of JPEG files to organise. I want to read the EXIF date and then move the files to folders like yyyy-mm (year / month). Files without EXIF data should be moved to a special folder. Can you help me?
Sure! Here is a PowerShell script that reads the EXIF date from JPEG files and organizes them into folders based on the year and month. Files without EXIF data will be moved to a separate folder.
Script and explanation …
ChatGPT liefert ein ca. 60-zeiliges Script, das die System.Drawing-Systembibliothek verwendet, um die EXIF-Daten auszuwerten. Dieser Lösungsweg ist zwar relativ umständlich, hat aber einen großen Vorteil: Es müssen keine weiteren Tools oder Bibliotheken installiert werden.
Ein erster Testlauf scheitert aber: Das Script öffnet jede Bilddatei zur EXIF-Analyse, schließt die Datei aber nicht wieder. Deswegen scheitert Move-Item bei jeder Datei mit einer Fehlermeldung.
Das ursprüngliche Script hat noch einen Mangel: Es berücksichtigt nur *.jpg-Dateien, aber keine *.jpeg-Dateien. Daher bitten Sie ChatGPT um Nachbesserung.
Prompt: Move-Item causes an error: »The process cannot access the file because it is being used by another process.« I guess the script needs to close the file before it can move it. Please also process *.jpeg files.
You are correct. The image files should be closed before moving them to avoid the “file in use” error. Additionally, we’ll include processing for *.jpeg files as well. Here’s the updated script:
...
$jpegFiles = Get-ChildItem -Path $sourceDir `
-Filter *.jpg, *.jpeg
...
ChatGPT sieht seinen Fehler ein und korrigiert das Script, baut aber sofort einen neuen Fehler ein: Die Option -Filter erwartet als Argument eine einzelne Zeichenkette, keine Aufzählung.
Prompt: $jpegFiles = Get-ChildItem -Path $sourceDir -Filter *.jpg, *.jpeg causes an error:
Cannot convert System.Object[] to the type System.String required by parameter Filter. Specified method is not supported.
I apologize for the mistake. The -Filter parameter only accepts a single string. We can handle both .jpg and .jpeg files by using Get-ChildItem twice or by using -Include with -Recurse. Here is the corrected script:
...
$jpegFiles = Get-ChildItem -Path $sourceDir `
-Include *.jpg, *.jpeg -Recurse
...
Erst das im dritten Versuch gelieferte Script funktioniert zufriedenstellend. Die nun eingesetzte Option -Recurse hat zudem den Vorteil, dass die PowerShell nicht nur das Bildverzeichnis, sondern auch alle Unterverzeichnisse verarbeitet. Dieses Verhalten sollte eigentlich selbstverständlich sein, wurde aber zugegebenermaßen im ursprünglichen Prompt nicht gefordert.
Irritierend bei diesem Beispiel ist die Trivialität der Fehler. Während das Grundkonzept des Scripts schon im ersten Versuch in Ordnung ist, sind die darin enthaltenen Fehler gewissermaßen »Anfängerfehler«. Sie untergraben das Vertrauen in das KI-Tool.
Python: SQLite-Anwendung
In einem Python-Script wollen Sie interne Daten mit SQLite organisieren. Sie kennen SQLite als minimalistische Bibliothek für kleine Datenbankanwendungen, haben SQLite aber noch nie zusammen mit Python verwendet.
Prompt: I am working on a Python script and want to use SQLite as a local database. Which module should I use? Do I need to install any additional libraries? Can you provide a short Hello-World-sample?
To use SQLite in Python, you can utilize the built-in sqlite3 module. There’s no need to install any additional libraries since sqlite3 is included with Python’s standard library. This module provides a lightweight disk-based database that doesn’t require a separate server process and allows access using a nonstandard variant of the SQL query language.
Here’s a short »Hello World« example of how to use SQLite with Python:
import sqlite3
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
cursor.execute("""CREATE TABLE hello_world
(id INTEGER PRIMARY KEY, message TEXT)""")
cursor.execute("""INSERT INTO hello_world (message)
VALUES ('Hello, World!')""")
conn.commit()
cursor.execute('SELECT * FROM hello_world')
print(cursor.fetchall())
# Output: [(1, 'Hello, World!')]
conn.close()
This script performs the following steps (more details …).
You can modify this example to interact with a file-based database by replacing ':memory:' with a file path, like 'example.db'.
ChatGPT liefert hier genau den richtigen Startpunkt für eigene Experimente. Mit einem kurzen Testlauf vergewissern Sie sich, dass das Script wirklich funktioniert. Anschließend versuchen Sie per KI-Chat, das Script an Ihre Bedürfnisse anzupassen.
Wir gehen im Weiteren davon aus, dass Sie VS Code und GitHub Copilot verwenden. Natürlich können Sie jede andere vergleichbare Kombination aus Editor und Code-Assistent einsetzen.
Prompt: I want to store an URL, an IP address (IPv4/IPv6) and a timestamp in a table. Can you adapt hello-world.py accordingly?
GitHub Copilot erzeugt daraufhin neuen Code und zeigt diesen im Chat-Bereich an (hier nicht abgedruckt). Allerdings müssen Sie den Code manuell in Ihr Script überführen.
Eine alternative Vorgehensweise besteht darin, den relevanten Code-Bereich zu markieren und Ihren Code-Wunsch mit (Strg)+(I) bzw. (cmd)+(I) in einem Inline-Chat zu formulieren. Das hat den Vorteil, dass VS Code nun tatsächlich vorschlägt, Ihre Code-Datei zu ändern. Sie können den neuen Code mit Accept oder Discard akzeptieren bzw. ablehnen.
Prompt: Please save the database persistent in log.db. If this file exists, open it. If not, create a new database with the web_data table.
Richtig »intelligent« ist das Inline-Chat-Verfahren allerdings noch nicht. Zum einen ist die Logik des Codes hier eindeutig falsch: Der Test, ob die Datenbank-Datei existiert, muss vor dem Öffnen bzw. Erstellen der Datenbank erfolgen. Zum anderen passt der neue Code nur teilweise zum ersetzten Code. Es fehlen Importe, Teile des Codes sind redundant etc. Wenn Sie den KI-Vorschlag übernehmen, müssen Sie den Code danach umfassend redigieren.
Abbildung 8.1 Bei diesem Beispiel hat GitHub Copilot keine optimale Arbeit geleistet. Die Logik des neuen Codes ist fehlerhaft, die Integration in den vorhandenen Code unvollständig.
Ein Blick in die Zukunft
Das Beispiel begründet, warum wir bei größeren Code-Änderungen eine vom Code getrennte Chat-Funktion vorziehen und den eigentlichen Code-Umbau lieber manuell durchführen. Aber natürlich ist es nur eine Frage der Zeit, bis Code-Assistenten schlau genug sind, um komplexe Code-Änderungen selbstständig durchzuführen.
Bash-Fehlersuche
ChatGPT kann auch bei der Fehlersuche helfen. Vor einiger Zeit wollten wir eine CSV-Datei verarbeiten. Deren beiden Spalten für URL und Datenbank waren mit Semikola getrennt. Wir haben versucht, die Spalten mit cut -d; zu zerlegen – aber das scheitert:
Prompt: The following Bash script does not work. Why?
tail -n +2 unused.csv | while IFS= read -r line; do
url=$(echo $line | cut -d; -f1)
db=$(echo $line | cut -d; -f2)
echo "url=$url db=$db"
done
ChatGPT ab Version 4 erkennt den Fehler auf Anhieb. (Sie auch?)
The issue with your script is likely due to the incorrect handling of the delimiter in the cut command. The delimiter needs to be specified properly, and special characters (like the semicolon ; in your case) should be quoted to ensure they are interpreted correctly by the shell. Here is how you can fix the code:
tail -n +2 unused.csv | while IFS= read -r line; do
url=$(echo "$line" | cut -d';' -f1)
db=$(echo "$line" | cut -d';' -f2)
echo "url=$url db=$db"
done
Ältere GPT-Versionen sind an diesem Beispiel übrigens gescheitert, ebenso die lokalen Modelle llama3:8b und gemma2:9b.
Python: rekursive Suche nach Dateien
Ausgangspunkt dieses Beispiels war die Arbeit an einem Script, das beginnend mit einem Startverzeichnis rekursiv alle darin befindlichen Dateien mit vorgegebenen Kennungen verarbeiten sollte (siehe auch Abschnitt 10.4, »Beispiel: Code automatisiert kommentieren«).
Prompt: Python: I need a function that returns all files in a directory (recursively) with given extensions. I will pass two parameters, directory path and a list of extensions (e.g. [".js", ".php"]). The code should run on Linux, macOS and Linux. Could you please help?
Certainly! Below is a Python function that will search through a directory recursively and return a list of all files that match the given extensions. This function uses the os and os.path modules for directory traversal.
def get_files_with_extensions(directory, extensions):
matching_files = []
for root, _, files in os.walk(directory):
for file in files:
if any(file.endswith(ext) for ext in extensions):
matching_files.append(os.path.join(root, file))
return matching_files
# example usage
print(get_files_with_extensions("/home/kofler",
[".js", ".php"])
More details …
Weitere Prompt-Beispiele
In diesem Abschnitt haben wir einige weitere Prompts aus unserer beruflichen Praxis zusammengestellt, uns aber die Darstellung der Ergebnisse bzw. die Diskussion der Ergebnisse gespart. Die Prompts sollen einfach als Anregung dienen.
Prompt: PowerShell: I need a script to scan my download directory for files older than 30 days. The script lists the files alphabetically (including size information) and offers to delete them after explicit confirmation (input of ‘yes’).
Prompt: Bash: I want to write a script that symmetrically encrypts all files which are passed as parameters. The encryption key (binary) is the content of /etc/secretkey. Add .crypt to the new file name and save it in the same directory as the old one. With the option --delete-original delete the original files.
Prompt: Bash: Write a script that uses ImageMagic to create JPEG thumbnails of the front page of all PDF files in a directory. For the thumbnail filenames, replace the .pdf extension with .jpg. Skip PDF files that already have a thumbnail.
Prompt: Python: I have a CSV file like this:
(20 lines of CSV text)
I need a script to visualize the column »energy consumption« over time. Can you help?
Prompt: Python/matplotlib: How can I label only every second point on the x-axis?
Prompt: Python: I want to display an image and interactively mark points on it. I need the x and y coordinates of these points. What are my options?