bash
Context Switching
Zuerst muss man sehen, was ein Context Switch überhaupt ist. Ganz einfach gesprochen ist es das, was auch mit nur einer CPU im System Multitasking ermöglicht.
Die Wikipedia definiert das ausführlicher:
Kontextwechsel oder Taskswitching (englischcontext switch) nennt man den Vorgang in einem Betriebssystem, bei dem die Bearbeitung des aktuellen Prozesses (oder auch Threads, Tasksoder Programms) unterbrochen wird (z. B. nach einer festgelegten Zeitspanne durch einen Timer-Interrupt oder bei Systemaufrufen) und zu einer anderen Routine gewechselt wird. Dabei wird derKontext (im Wesentlichen die Prozessor-Register) des aktuellen Prozesses/Threads/Tasks gesichert und der Kontext des neuen restauriert. Durch diesen Vorgang wird Multitasking ermöglicht, da sich so mehrere Prozesse im Zeit-Multiplexverfahren auf einem einzelnen CPU-Kern mehr oder weniger gleichzeitig ausführen lassen.
Wie aufwändig ist jetzt ein Context Switch? Dieser Frage wird ein einem Blogartikel nachgegangen: Also im Worst case 4500 ns. Schon klar, das kann deutlich besser aussehen, je nach verwendetem System oder auch der verwendeten CPU.
Wie viele Context switches passieren denn so auf einem System? Am einfachsten eniemal mit dem SAR command nachsehen:
# sar -w 1 10000 Linux 2.6.34.10-0.6-default (ServerWalterschlag) 03/09/14 _i686_ (1 CPU)
10:37:57 proc/s cswch/s 10:37:58 0.00 157.00 10:37:59 0.00 158.00 10:38:00 0.00 319.80 10:38:02 0.00 161.00 10:38:03 0.00 159.41 10:38:04 0.00 165.35 10:38:05 0.00 150.00 10:38:06 0.00 199.00 10:38:07 0.00 184.16 10:38:08 0.00 275.76 10:38:09 0.00 190.10 10:38:10 0.00 154.90 10:38:11 0.00 273.00 10:38:12 0.00 1380.20 10:38:13 0.00 2915.00 10:38:14 0.00 2785.00 10:38:15 0.00 3614.00 10:38:16 0.00 3548.00 10:38:17 0.00 2745.00 10:38:18 0.00 2072.28 10:38:19 0.00 2262.38
Das kann ganz schön Schwanken, je nachdem wie viele Prozesse da aktuell laufen. Aber ausgehend von den 2200 context switches jede Sekunde und 4500 ns pro context switch würde das 9,9ms allein für context switche ergeben. Das System würde also ca. 1% seiner Zeit mit der Prozessverwaltung verbringen. Das ist so gut wie zu vernachlässigen. Steigt aber die Prozessanzahl und die Contextswitches weiter an, um etwa einen Faktor 10, dann wird die Anzahl der Switches interessant.
Weitere Betrachtungen wären nötig, für Systeme mit mehreren CPUs – für eine erste Näherung würde ich einfach die Anzahl der Context Switche durch die Anzahl der vorhandenen CPUs dividieren, da die Prozessorkerne ja gleichzeitig die Switches durchführen können.
Bash Array
Nur ein Beispiel, wie man ein Array auf der Bash benutzen kann.
Als erstes die Definition von zwei Arrays:
XX=("x1" "x2") XY=("y1" "y2")
Dann das Anwendungsbeispiel, wichtig vor allem, dass die Elemente gezählt werden:
for (( i = 0; i < ${#XX[@]}; i++ )) do echo "${XX[$i]} ${XY[$i]}" done
Dann das Anwendungsbeispiel, wichtig vor allem, dass die Elemente gezählt werden:
x1 y1 x2 y2
Locking auf der Bash
Da ich es mit meiner Erklärung sogar ins Linux Magazin zu den Leserbriefen geschafft habe, schreibe ich hier auch noch ein paar Worte zum Locking in Shell-Scripten.
Mit dem Tool "flock" lässt sich in Shell-Scripten ein ganz einfaches Locking realisieren. Und zwar ohne, dass man sich um ein eigenes Lock-File bzw. um das entfernen des Selbingen kümmern muss.
Günstig ist z.B. wenn es bereits ein Backup-Script gibt:
server:~/tmp # time ./backup.sh mache backup - irgendwas mit rsync fertig real 0m5.033s user 0m0.004s sys 0m0.004s
Jetzt möchte ich einen Locking-Mechanismus haben, der verhindert, dass das Script 2x gleichzeitg läuft:
flock -w1 -x ./backup.sh ./backup.sh
Das führt dazu, dass ein Kernel-Lock angefordert wird, der eindeutig ist, weil er sich auf das Script bezieht.
Was soll jetzt geschehen, wenn der Lock nicht erfolgreich war? Mit dem Parameter w wurde ein Timeout mitgegeben. D.h. nach einer Sekunde wird abgebrochen. Wie bekomme ich mit, dass das Script gar nicht gelaufen ist?
flock -w1 -x ./backup.sh ./backup.sh || echo es gab ein problem
Ich lasse es mir einfach ausgeben… oder per Mail schicken. Aber das soll ruhig eine Übung für den Leser bleiben.
dd optimieren
dd ist ein Tool um Dateien und Geräte blockweise zu kopieren. Erst kürzlich kam eine Anfrage zu mir, wie denn die Geschwindigkeit von dd gesteigert werden könnte. Im konkreten Fall ging es auch noch darum, die Daten übers Netzwerk zu übertragen.
1) Komprimierung verwenden
dd if=/dev/sdX bs=1024 count=1024 | gzip -9 | ssh root@192.168.XXX.XXX "gunzip | dd of=/tmp/testfile"
2) Blockgröße einstellen
Die Auswirkung der Blockgröße habe ich mal etwas durchprobiert. In diesem Diagramm, sieht es so aus, als würde die Blockgröße nicht viel bringen. Der default Wert auf dem Test-System war genau ein Block der Festplatte mit 512 Byte. Das anheben der Blockgröße auf deutlich über 1MB bringt je nach Test 30 – 60 % mehr Geschwindigkeit.
Wait I/O
Wait I/O wird immer dann angezeigt, wenn ein Prozess auf die Festplatte warten muss. …
Was kann man gegen Wait I/O tun?
Neben den offensichtlchen sachen, wie z.B. schnellere Festplatten, performantere RAID Levels oder gleich einer SSD gibt es noch eine, zugegeben nutzlose Möglichkeit, den Wait I/O zu reduzieren.
Mit einer leeren Schleife pro CPU Kern, wird die Nutzung so gewandelt, dass sie statt I/O-lastig plötzlich CPU-lastig ist:
while true; do true; done
Abra Ka Kosmetik – die Wait I/O ist verschwunden 😉
PS: Macht das nicht zu Hause (auf einem Produktiv-System) nach…
Dateinamen aus einer Liste extrahieren
Hier die Liste:
# cat test.lst X:KRIS KRISTOFFERSONKRIS KRISTOFFERSON - HELP ME MAKE IT THROUGH THE NI - SINGLE - 1980 - COUNTRY - 0.MP3|TAG|KRIS KRISTOFFERSON|HELP ME MAKE IT THROUGH THE NI||SINGLE|1980|0|COUNTRY|MP3|0|141296|0|327680|0|0|-1|0|0|0|3|192|10|-1|0|0|0|-1472508263|0||0|-1|-1| X:ENGLISCHCCARLENE CARTERCARLENE CARTER - EVERY LITTLE THING - SINGLE - 1980 - DANCE - 0.MP3|TAG|CARLENE CARTER|EVERY LITTLE THING||SINGLE|1980|0|DANCE|MP3|0|192992|0|327680|0|0|-1|0|0|0|3|128|10|-1|0|0|0|804889938|0||0|-1|-1| X:TOM ASTOR UND WOLFGANG PETRY - TAKE ME HOME - FOX.MP3|TAG|TOM ASTOR UND WOLFGANG PETRY|TAKE ME HOME|FOX||2006|||MP3|0|177972|0|327680|0|0|-1|0|0|0|3|192|10|-1|0|0|0|-1510661211|18||43283610|-1|-1| X:TEXAS COUNTRYTEXAS COUNTRY - HEARTACHE COUNTY.MP3|TAG|TEXAS|COUNTRY||- HEARTACHE COUNTY|1999|TRACK|COUNTRY|MP3|0|178364|0|327680|0|0|-1|0|0|0|3|128|10|-1|0|0|0|-742867055|0||0|-1|-1|
Aufgabe: Extrahiere den Dateinamen:
# cut -d"|" -f1 test.lst | awk -F '' '{ print $NF }' KRIS KRISTOFFERSON - HELP ME MAKE IT THROUGH THE NI - SINGLE - 1980 - COUNTRY - 0.MP3 CARLENE CARTER - EVERY LITTLE THING - SINGLE - 1980 - DANCE - 0.MP3 TOM ASTOR UND WOLFGANG PETRY - TAKE ME HOME - FOX.MP3 TEXAS COUNTRY - HEARTACHE COUNTY.MP3
Howto: Screen
Screen ist ein kleines Programm, welches einen eigenen "Bildschirm" öffnet. Dieser läuft auch nach dem ausloggen der Shell weiter und kann in einer anderen Sitzung wieder übernommen werden.
Screen starten:
screen
Wieder ausloggen: [Strg + a]; d(etatch)
Vorhandene Screen-Sitzungen auflisten:
server:~ # screen -list There is a screen on: 27272.pts-4.server (Detached) 1 Socket in /var/run/screens/S-root.
Eine Sitzung forsetzten
screen -r(esume) [PID]
PID ist nur notwendig, wenn bereits mehr wie eine Sitzung läuft.
Logging und Netzwerkverbindungen in der Bash
Inspiriert vom Artikel Bash Bashing aus dem Linux Magazin 12/2010 hab ich mich etwas näher mit den Fähigkeiten der Bash beschäftigt.
Zwei interessante Punkte habe ich dabei entdeckt: …
- Mit dem Shell-Builtin „exec“ lassen sich ganz einfach Filedescriptoren verbiegen. Das Beispiel dazu im Artikel schreibt dazu:
exec 77>&1
, das heißt es wird der Deskriptor 1 – die Standardausgabe – mit dem Deskriptor 77 verbunden. Das dient eigentlich dazu, dass die Standardausgabe gesichert wird, um diese später wiederherstellen zu können. Dabei stellt sich mir allerdings die Frage warum gerade der Deskriptor 77 verwendet wird. Es kann dann mit
exec > /tmp/logfile
die gesamte Ausgabe aller folgenden Befehle in eine Datei umgelenkt werden, ohne diese extra angeben zu müssen. Wiederhergestellt wird die Standardausgabe dann über den Befehl
exec 1>&77
- Der zweite wichtige Punkt ist der, dass die Bash bereits alles wichtige mitbringt um eine Netzwerkverbindung aufzubauen. Das sollte sich auch problemlos mit Punkt 1 kombinieren lassen. Um etwa eine Datei von einem Webserver herunterzuladen wird kein zusätzliches Werkzeug wie wget benötigt.
Das Ergebnis war dieses Beispielscript mit dem z.B. eine Webseite heruntergeladen werden kann:#!/bin/bash # exec: bash builtin # exec 5<> filedescriptor 5 mit netzwerksocket verbinden # host www.orf.at; port 80 exec 5<> /dev/tcp/www.orf.at/80 # etwas an den socket schicken echo -e "GET / HTTP/1.0\n" >&5 # antwort vom socket abholen (und in ein Datei outputfile schreiben) cat <&5 > outputfile
Eine Anleitung zu dem Ganzen findet sich auch unter „/dev/tcp“ im „Advanced Bash Scripting Guide“.
chmod -x chmod
Vor einiger Zeit schon gesehen, aber jetzt wieder gefunden.
Sollte man dem chmod-Befehl das Recht nehmen, gestartet zu werden – wie kann man es wieder herstellen. Einige mehr oder weniger kreative Ideen zeigt diese Präsentation: …
Filedescriptoren in Shellscripten
Interessanter Hinweis für Filedescriptoren in Shellscripten: