script
grep -v
Wie sucht man ob ein Prozess läuft?
# ps aux | grep smb root 699 0.0 0.4 28800 4036 ? Ss Oct22 0:43 smbd -F root 768 0.0 0.1 28800 1604 ? S Oct22 0:04 smbd -F root 21411 0.0 0.0 4680 772 pts/0 S+ 18:06 0:00 grep --color=auto smb
Das ist zuviel Output, weil auch der grep-Prozess selber angezeigt wird. Dafür gibt es eine einfältige Lösung:
# ps aux | grep smb | grep -v grep root 699 0.0 0.4 28800 4036 ? Ss Oct22 0:43 smbd -F root 768 0.0 0.1 28800 1604 ? S Oct22 0:05 smbd -F
Aber wie geht es besser?
ps aux | grep [s]mb root 699 0.0 0.4 28800 4036 ? Ss Oct22 0:43 smbd -F root 768 0.0 0.1 28800 1604 ? S Oct22 0:05 smbd -F
Warum funktioniert das? Ganz einfach, weil in der Prozessliste jetzt der String „smb“ nicht mehr vorkommt beim grep-Befehl, sondern der String „[s]mb“. Gesucht wird von dem Befehl aber trotzdem nach „smb“.
Braucht man nur die PID vom Prozess geht es aber einfacher:
# pgrep smb 699 768
Soll das ganze nur zum Beenden der Prozesse genutzt werden, braucht man gar keinen grep mehr.
# killall smbd
Dateien nach Datum Sortieren
Dateien sortieren nach Datum geht mit dem simplen „ls“ mit der Option „-t“.
Aber wie geht das Übergreifend über verschiedene Ordner?
$ ls Windows/* Programme/* -ldt drwxr-x--- 1 42949672 42949672 0 Oct 22 20:48 Windows/Prefetch -rwxrwx--- 1 SYSTEM 42949672 275 Oct 22 20:24 Windows/WindowsUpdate.log drwxr-x--- 1 42949672 42949672 0 Oct 22 20:14 Windows/Temp drwxrwx--- 1 42949672 42949672 0 Oct 22 20:10 Windows/Microsoft.NET drwxrwx--- 1 SYSTEM 42949672 0 Oct 22 19:28 Windows/AppReadiness -rwxrwx--- 1 SYSTEM 42949672 67584 Oct 22 19:18 Windows/bootstat.dat drwxrwxr-x 1 Administ 42949672 0 Oct 21 21:08 Windows/Installer drwxrwx--- 1 SYSTEM 42949672 0 Oct 21 21:07 Programme/Java drwxrwx--- 1 42949672 42949672 0 Oct 21 21:03 Windows/INF -rwxrwx--- 1 SYSTEM 42949672 34668 Oct 20 21:18 Windows/setupact.log drwxr-x--- 1 42949672 42949672 0 Oct 20 19:23 Windows/WinSxS drwxrwx--- 1 Administ 42949672 0 Oct 20 19:20 Windows/CbsTemp drwxrwx--- 1 42949672 42949672 0 Oct 20 19:20 Windows/SysWOW64 drwxrwx--- 1 42949672 42949672 0 Oct 20 19:20 Windows/System32 drwxrwx--- 1 SYSTEM 42949672 0 Oct 14 19:13 Programme/NVIDIA Corporation drwxrwx--- 1 SYSTEM 42949672 0 Oct 14 19:13 Windows/Help -rwxrwx--- 1 Administ 42949672 4882 Oct 13 22:18 Windows/PFRO.log drwxrwx--- 1 42949672 42949672 0 Oct 13 22:18 Windows/AppPatch drwxrwx--- 1 42949672 42949672 0 Oct 13 20:57 Windows/Fonts drwxrwx--- 1 42949672 42949672 0 Oct 13 20:57 Windows/twain_32 drwxrwx--- 1 SYSTEM 42949672 0 Oct 13 20:57 Programme/HP drwxrwx--- 1 Administ 42949672 0 Oct 13 20:49 Windows/assembly -rwxrwx--- 1 SYSTEM 42949672 478 Oct 13 20:06 Windows/win.ini drwxrwx--- 1 SYSTEM 42949672 0 Oct 13 20:04 Windows/PCHEALTH drwxrwx--- 1 42949672 42949672 0 Oct 5 18:48 Windows/L2Schemas drwxrwx--- 1 42949672 42949672 0 Oct 5 18:48 Windows/Provisioning drwxrwx--- 1 42949672 42949672 0 Oct 5 18:48 Windows/PurchaseDialog drwxrwx--- 1 SYSTEM 42949672 0 Sep 20 08:30 Programme/Oracle drwxrwx--- 1 Administ Administ 0 Sep 19 08:58 Windows/Tasks drwxrwx--- 1 42949672 42949672 0 Sep 9 18:28 Programme/Windows Journal drwxrwx--- 1 SYSTEM 42949672 0 Sep 6 08:52 Programme/Calibre2 drwxrwx--- 1 42949672 42949672 0 Aug 22 08:51 Windows/DevicesFlow drwxrwx--- 1 Administ UsersGrp 0 Aug 18 22:16 Programme/FileZilla FTP Client drwxrwx--- 1 SYSTEM 42949672 0 Aug 15 17:30 Programme/7-Zip ...
Sortierung umdrehen:
ls Windows/* Programme/* -ldrtR -rwxrwx--- 1 SYSTEM 42949672 1405 Jun 10 2009 Windows/msdfmap.ini -rwxrwx--- 1 SYSTEM 42949672 219 Jun 10 2009 Windows/system.ini -rwxrwx--- 1 SYSTEM 42949672 302448 Mar 8 2012 Windows/WLXPGSS.SCR drwxrwx--- 1 Administ 42949672 0 Feb 2 2015 Windows/CSC -rwxrwx--- 1 SYSTEM 42949672 1313 Feb 2 2015 Windows/TSSysprep.log lrwxrwxrwx 1 SYSTEM 42949672 36 Feb 2 2015 Programme/Gemeinsame Dateien -> /drives/c/Program Files/Common Files drwxrwx--- 1 SYSTEM 42949672 0 Feb 2 2015 Programme/Microsoft Analysis Services drwxrwx--- 1 SYSTEM 42949672 0 Feb 2 2015 Programme/Microsoft Sync Framework drwxrwx--- 1 SYSTEM 42949672 0 Feb 2 2015 Programme/Microsoft SQL Server Compact Edition drwxrwx--- 1 SYSTEM 42949672 0 Feb 2 2015 Programme/Microsoft Office drwxrwx--- 1 SYSTEM 42949672 0 Feb 2 2015 Programme/Microsoft Synchronization Services -rwxrwx--- 1 Administ UsersGrp 202 Feb 3 2015 Windows/DirectX.log drwxrwx--- 1 SYSTEM 42949672 0 Feb 3 2015 Programme/Windows Live -rwxrwx--- 1 SYSTEM 42949672 15936 Feb 4 2015 Windows/IE11_main.log drwxrwx--- 1 Administ UsersGrp 0 Feb 7 2015 Programme/Tracker Software -rwxrwx--- 1 Administ UsersGrp 10446 Apr 28 10:36 Windows/DPINST.LOG drwxrwx--- 1 Administ UsersGrp 0 Apr 28 10:52 Windows/Hewlett-Packard ...
Bash: Variablen Bearbeiten
Die Bash kann einiges mit Variablen anstellen, was man in vielen Scripten relativ kompliziert gelöst sieht.
Ein Beispiel, das in vielen Scripten vorkommt: Eine Ausgabedatei soll genau so heißen wie die Eingabedatei, aber eine andere Erweiterung haben.
A="test.txt" B="${A%%.txt}.csv"
Was steht jetzt in Variable B?
echo $B test.csv
Wie funktioniert das?
Mit dem ‚%‘-Operator kann man von einer Variable Zeichen vom Ende her löschen.
Mit ‚%%‘ werden auch mehrere Vorkommen der Variable vom Ende her gelöscht.
Vom Anfang her löschen geht mit ‚#‘
Ersetzen ähnlich wie mit sed geht über den ‚/‘-Operator, ‚^‘ und ‚,‘ machen Groß- bzw. Kleinbuchstaben.
Schöne Beispiele dazu finden sich im Web z.B. beim Linuxmagazin.
Näheres dazu ist unter dem Suchbegriff „Parameter Expansion“ zu finden. Auch in der Manpage von bash.
Powershell
Microsoft macht einem das Scripten mit Powershell schon mal ziemlich schwer:
PS C:\tmp> .\test.ps1 Die Datei "C:\tmp\test.ps1" kann nicht geladen werden, da die Ausführung von Sk ripts auf diesem System deaktiviert ist. Weitere Informationen erhalten Sie mit "get-help about_signing". Bei Zeile:1 Zeichen:11 + .\test.ps1 <<<< + CategoryInfo : NotSpecified: (:) [], PSSecurityException + FullyQualifiedErrorId : RuntimeException
So soll man das Ausführen von Scripten erlauben können:
Set-ExecutionPolicy Unrestricted
Das hilft aber auch nicht immer:
Set-ExecutionPolicy : Der Zugriff auf den Registrierungsschlüssel "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\Shel lIds\Microsoft.PowerShell" wurde verweigert. Bei Zeile:1 Zeichen:20 + Set-ExecutionPolicy <<<< Unrestricted + CategoryInfo : NotSpecified: (:) [Set-ExecutionPolicy], UnauthorizedAccessException + FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand
Um das zu lösen, müssen wir den Registrierungseditor bemühen:
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell] "ExecutionPolicy"="Unrestricted"
Update: Quelle
bash: translate
Was macht tr?
tr - translate or delete characters
Wie kann man Zeichen löschen?
-d, --delete
delete characters in SET1, do not translate
Ein Testfile:
# cat test
a
b
c
d
Dann ersetzen wir mal die Zeilenumbrüche:
# cat test | tr "\n" -d
a-b-c-d-
Ups – so nicht! Das verhält sich anders als in der Man Page beschrieben…
Aber mit der anderen Reihenfolge der Parameter – schon klappt es:
cat test | tr -d "\n"
abcd
Die Bash austricksen
Folgende Problemstellung: In einem Shellscript soll eine Variable unter einfachen Hochkomma eingefügt werden. Von Haus aus geht das nicht, weil das einfache Hochkomma die Variable vor dem Auflösen durch die Shell schützt. Durch doppelte Hochkomma ersetzen geht auch nicht, weil die ebenfalls schon vorkommen und erhalten bleiben sollen weil diese Syntax noch vom nächsten Tool an diesen Stellen nötig sind.
> X=xy > echo '"ab" "cd" "$X"' "ab" "cd" "$X"
So klappt es schon mal nicht. Statt $X hätten wir gerne „xy“ da stehen. Was liegt also näher, als mit dem gut alten sed zu ersetzen?
echo $(echo '"ab" "cd" "$X"' | sed s/\$X/$X/g) "ab" "cd" "xy"
Schon klappt die Ersetzung.
Wie funktioniert das jetzt genau? Im sed wird der String „$X“ mit dem Inhalt von $X ersetzt. Wichtig ist dabei das $-Zeichen mit einem \ zu quoten.
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.
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“.
Filedescriptoren in Shellscripten
Interessanter Hinweis für Filedescriptoren in Shellscripten: