Das Shell-Blog http://martin.ringehahn.de/shellblog #!/bin/bash Wed, 09 Aug 2006 13:36:57 +0000 http://wordpress.org/?v=2.7.2-alpha en hourly 1 vim tricks 2 http://martin.ringehahn.de/shellblog/?p=145 http://martin.ringehahn.de/shellblog/?p=145#comments Wed, 09 Aug 2006 13:36:57 +0000 chrono http://martin.ringehahn.de/shellblog/?p=145 Wenn man mal von irgendwoher code in den VIM per Maus pasten muss, kommt man oft mit der automatischen Einrückung und ähnlichen dingen in Konflikt. Ausweg ist -ganz trivial- vor dem pasten ein :set paste und danach wieder ein :set nopaste.

]]>
http://martin.ringehahn.de/shellblog/?feed=rss2&p=145
vim tricks http://martin.ringehahn.de/shellblog/?p=144 http://martin.ringehahn.de/shellblog/?p=144#comments Mon, 26 Jun 2006 14:10:16 +0000 chrono http://martin.ringehahn.de/shellblog/?p=144 Tip #422: A Quick Reference

Ctrl-a, Ctrl-x

increase, decrease by 1 the number under the cursor (5Ctrl-a increases by 5)

]]>
http://martin.ringehahn.de/shellblog/?feed=rss2&p=144
Die Zsh-Liebhaber-Seite http://martin.ringehahn.de/shellblog/?p=143 http://martin.ringehahn.de/shellblog/?p=143#comments Mon, 20 Mar 2006 12:14:46 +0000 chrono http://martin.ringehahn.de/shellblog/?p=143 moechte ich euch natuerlich nicht vorenthalten. grad auf der suche nach der zsh repeat-syntax drueber gestolpert:

Die Zsh-Liebhaber-Seite

]]>
http://martin.ringehahn.de/shellblog/?feed=rss2&p=143
Shortcut fuer den letzten Parameter http://martin.ringehahn.de/shellblog/?p=142 http://martin.ringehahn.de/shellblog/?p=142#comments Fri, 17 Jun 2005 13:49:27 +0000 chrono http://martin.ringehahn.de/shellblog/?p=142 Wie schon im Bash Advanced Artikel erwaehnt, kann man ja den letzten Parameter des letzten Befehls mit !$ referenzieren. Wenn man allerdings daran noch was aendern oder ergaenzen moechte, dann eignet sich ALT-., damit kommt der direkt in die aktuelle Befehlszeile.

Am Rande noch einen kleinen, feinen Link: Unterrichtsmaterial von Kristian Koehntopp zur Shellprogrammierung

]]>
http://martin.ringehahn.de/shellblog/?feed=rss2&p=142
less vs tail http://martin.ringehahn.de/shellblog/?p=141 http://martin.ringehahn.de/shellblog/?p=141#comments Sat, 04 Jun 2005 09:58:01 +0000 chrono http://martin.ringehahn.de/shellblog/?p=141 Eigentlich sollte man ja den Befehl tail kennen

tail(1)                  - display the last part of a file

mit tail -f kann man Dateien fortlaufend anzeigen, z.b. um Logfiles zu beobachten

-f  The -f option causes tail to not stop when end of file is
    reached, but rather to wait for additional data to be appended to
    the input.

der Befehl less kennt dieses verhalten auch, einfach im less F druecken.

]]>
http://martin.ringehahn.de/shellblog/?feed=rss2&p=141
Eine leichte Aenderung im ShellBlog http://martin.ringehahn.de/shellblog/?p=140 http://martin.ringehahn.de/shellblog/?p=140#comments Sat, 04 Jun 2005 09:46:35 +0000 chrono http://martin.ringehahn.de/shellblog/?p=140 Deifl hat im IRC angeregt, dass doch was kurzes, handfestes sinnvoll sein koennte. Ergo: erwartet ab&zu einfache hints — kann durchaus sein das die jeder schon kennt, manche kennen die halt noch ned. Ende der Durchsage.

]]>
http://martin.ringehahn.de/shellblog/?feed=rss2&p=140
In eigener Sache http://martin.ringehahn.de/shellblog/?p=128 http://martin.ringehahn.de/shellblog/?p=128#comments Thu, 03 Feb 2005 13:56:56 +0000 chrono http://martin.ringehahn.de/shellblog/?p=128 Ich habe heute das ShellBlog auf Wordpress umgezogen, da ich keine Lust mehr hatte, MT immer wieder zu patchen und Perl gefaellt mir zum rumhacken nicht so. Also jetzt, das gleiche WP wie mein Blog und mein Linkdump - so muss ich nur noch ein System pflegen. Die Permalinks funktionieren weiterhin, wie das geht hab ich schonmal beschrieben. Die FeedReader sollten sich auch an die neue URL gewoehnen, permanente Redirects sind gesetzt. Einziger Unterschied: Statt die index.rdf wird jetzt auf eine rss2-Datei umgeleitet, da dort der komplette Post durchkommt und nicht nur ein Auszug.

Ob ich in naechster Zeit mal wieder dazu komme, einen Artikel zu schreiben? Wer weis — dieser Feed steht bei mir im NetNewsWire ganz oben auf der “Dinosaur”-Liste also muesste mal wieder was kommen. Derzeit bissl Pruefungsstress also fruehestens April.

]]>
http://martin.ringehahn.de/shellblog/?feed=rss2&p=128
Lektion 6: Bash Advanced http://martin.ringehahn.de/shellblog/?p=127 http://martin.ringehahn.de/shellblog/?p=127#comments Sun, 26 Oct 2003 20:27:06 +0000 chrono http://martin.ringehahn.de/shellblog/?p=127 Bis jetzt haben wir nur die Spitze des Eisbergs “Bash” berührt. Die Bash kann noch viel mehr. Diesmal: Klammerauswertung, Shortcuts, History-Navigation Öfters möchte man die Ausgabe eines Programmes als Parameter an ein anderes übergeben. Beispiel: Ich will in mehreren Dateien nach einem Begriff suchen:
grep Suchbegriff *.tex. Klar, klappt einwandfrei. Was, wenn ich aber komplexere Dateieinschränkungen machen möchte? Dann kann ich z.b. folgendes machen: grep Suchbegriff find . *.tex sucht rekursiv in diesem Verzeichnis alle tex-Dateien und “grep”t diese. Alternativ: grep Suchbegriff $(find . *.tex) - damit kann man diese Sub-Kommandos noch verschachteln. Dummerweise gibts da eine Beschränkung der Parameterlänge. Wenn also zu viele Dateien gefunden werden, gibts ein Problem. Ausweg: xargs (man xargs). Beispiel: find . *.tex | xargs grep Suchbegriff.

Ich gebe ab und zu etwas komplexe Befehlsketten ein. Ich habe natürlich keine Lust, die jedes mal neu einzugeben oder lange mit den Cursortasten in der History zu suchen. Lösung: inkrementelle Rückwärtssuche in der History: C-R (Control-R) drücken und Suchbegriff eingeben. Die Kommandozeile wird automatisch ergänzt.
Das letzte Kommando einfach nochmal ausführen? Kein Problem: einfach !! eintippen, fertig. Einfach den letzten ssh-Befehl nochmal ausführen? !ssh, der erste Treffer in der History wird direkt Ausgeführt. Wenn ich doch noch mal sehen will, was da Ausgeführt werden soll, dann tippe ich !ssh:p der Doppelpunkt als Trenner, p für Print. Wenn ich das dann ausführen möchte, einfach !!. Man kann sich ja auch die History anzeigen lassen. z.B mit history | less - da stehen da die Befehle durchnummeriert da. Wenn man einen bestimmten Befehl ausführen möchte - einfach !X wobei X der Nummer entspricht. Nächstes gimmick: man stelle sich vor, ich suche in einer Datei nach einem Begriff. z.B. grep ringehahn /usr/local/etc/apache/httpd.conf und möchte danach diese Datei bearbeiten. Da der Pfad ziemlich lang ist, möchte ich ihn nicht nochmal eintippen. !$ referenziert den letzten Parameter des letzten Befehls. Also ist es nun ein einfaches den Editor aufzurufen: vim !$ - super, oder?
Jetzt hab ich in dem Verzeichnis noch ein paar andere Dateien zu bearbeiten, wie komm ich dahin? Klar, tippen ist keine Option, jeder Informatiker ist ein faules Schwein. Einfach cd !$:h eintippen, fertig. Liste der anhängsel:
h
Pfad ohne Dateiname
t
Dateiname ohne Pfad
r
voller Pfad mit Dateinamen, nur ohne dessen Endung
e
nur die Endung des Dateinamens
Ich möchte nicht das letzte Argument des letzten Befehls, sondern des vorletzten Befehls: echo $-2! Ich habe einen Tippfehler beim letzten Befehl gemacht. z.B. grep ringelhahn /usr/local/etc/apache/httpd.conf und möchte den Befehl nun korrigiert starten: ^elhahn^ehahn und der Befehl wird korrigiert ausgeführt. Prinzip: ^Fehler^Korrektur
Klammerauswertung #2:
Schnell ein Backup einer Datei anlegen? Klar: cp datei datei-bck. Einfacher: cp datei{,-bck}. Backup zurueckkopieren? cp datei{-bck,}. Alles in /usr/local/(s?)bin anzeigen? ls /usr/local/{s,}bin. Alle Dateien verschiedener Typen anzeigen? ls *.{tex,latex,pdf,html}

vieles hier ist eine schamlose Kopie von Deadmans “Advancing in the Bash Shell”

]]>
http://martin.ringehahn.de/shellblog/?feed=rss2&p=127
Lektion 5: Arbeiten mit entfernten Rechnern http://martin.ringehahn.de/shellblog/?p=121 http://martin.ringehahn.de/shellblog/?p=121#comments Sat, 11 Oct 2003 22:04:52 +0000 chrono http://martin.ringehahn.de/shellblog/?p=121 Im laufe eines normalen Tages arbeite ich durchschnittlich an 5 Rechnern. Zwei davon stehen bei mir im Zimmer, der Rest steht woanders (weiter als 5 Schritte entfernt, also “Remote”). Nun, ich könnte wie z.b. in Windows-Kreisen durchaus üblich, vnc oder Remote-X verwenden um auf den Kisten was zu tun. Ist aber alles langsam (z.b. die DSL-Kiste zuhause) oder X (Grafikoberfläche) ist gar nicht installiert (wozu auch, auf dem Server). Also wie nutze ich die Rechner entfernt? Klar, mit ssh. ssh steht für “secure shell” und eignet sich prinzipiell für verschlüsselte, authentifizierte Datenübertragung. Mit dem Befehl ssh user@ein.anderer.rechner.example kann ich mich bei dem Rechner “ein.anderer.rechner.example” unter dem Nutzerkonto “user” anmelden, ich werde nach dem Passwort gefragt und ich bin drin. Sehr einfache, schnelle Geschichte. Was aber wenn ich nicht ständig mein Passwort (wenn auch verschlüsselt) durch das (Inter-)Netz schicken will? Dafür kennt ssh andere Authentifizierungsmethoden. Zum Beispiel public/private Schlüsselpaare, wie sie auch bei Email-Verschlüsselung (gpg/pgp) eingesetzt werden. Das Konzept in Kurzform: Der Benutzer erzeugt ein Schlüsselpaar (einen öffentlichen, einen privaten Schlüssel). Diese Schlüssel werden auf dem lokalen Rechner gespeichert. Auf dem entfernten Rechner, bei dem man sich einloggen will speichert man den öffentlichen Schlüssel. Möchte man sich nun auf dem entfernten Rechner anmelden, sendet der entfernte Rechner eine, mit dem öffentlichen Schlüssel verschlüsselte Zufallszahl, welche der lokale Rechner mit dem privaten Schlüssel (und evtl Passwortabfrage für diesen) entschlüsselt. Die entschlüsselte Zahl wird zurück an den entfernten Rechner gesendet, welcher nun (wenn die Zahlen übereinstimmen) den Benutzer “authentifiziert” hat. Dabei wurde weder der öffentliche noch der private Schlüssel über das Netz geschickt, lediglich eine Zufallszahl. Sehr elegant, oder? (nebenbei: hier (unter anderem) erkennt man auch die Wichtigkeit von “zufälligen” Zufallszahlen für Verschlüsselungsverfahren.; achja nochwas: der entfernte Rechner authentifiziert sich auch selbst: gleiches Prinzip - öffentlicher Schlüssel bei uns, privater Schlüssel auf entferntem Rechner)
Erzeugung des Schlüsselpaares (für ssh Version 2):
ssh-keygen -t dsa
Man sollte für den privaten Schlüssel ein Passwort setzen, so wird selbst ein gestohlener privater Schlüssel nicht automatisch zum Einfallstor. Die Schlüssel werden unter ~/.ssh/iddsa (privater) und ~/.ssh/iddsa.pub (öffentlicher) abgelegt. Nun muss man dem entfernten Rechner seinen öffentlichen Schlüssel mitteilen. Die öffentlichen Schlüssel (es können mehrere sein) liegen auf dem entfernten Rechner unter ~/.ssh/authorizedkeys , pro Zeile ein Schlüssel. Falls dort die Datei noch nicht Existiert, kann man die iddsa.pub einfach drüberkopieren. Zu diesem Zweck kann jetzt ein anderes Programm der ssh-Familie zum Einsatz kommen: scp - Secure Copy. Kopieren von Dateien über verschlüsselte Verbindung. Siehe Manpage. scp ~/.ssh/iddsa.pub user@ein.anderer.rechner.example:.ssh/authorizedkeys
Damit sollte das Problem des “Passwort über Netzwerk” gelöst sein. Nächstes Problem: Ich bin zu faul ständig mein langes, kompliziertes (daher: sicheres) Passwort einzugeben. Lösung: ssh-agent. Diesem Programm bringt man mittels ssh-add das Passwort für den/die privaten Schlüssel bei, ssh verwendet den Agenten um die Zufallszahl zu entschlüsseln. Den Agenten einzurichten kann etwas kompliziert sein. Ich verwende trotz aller Shell-Spielereien eine graphische Oberfläche (X+WindowMaker um genau zu sein). Damit alle Programme (unterhalb von WindowMaker) den Agenten verwenden können, lasse ich den WindowMaker durch ssh-agent starten. Wie das genau geht, ist in den Distributionen ziemlich unterschiedlich; Google hilft.
ssh bietet ziemlich viele Möglichkeiten. Ich kann z.b. auch sichere Tunnels graben, entfernte graphische Programme verschlüsselt starten, den privaten Schlüssel aus Wechselmedien (z.b. USB-Stick, Smartcard) lesen, gzip Kompression der Daten aktivieren et cetera.
Ich finde ausserdem, dass es wichtig ist auf die Konfigurationsdatei hinzuweisen. Dort kann man z.b. host-spezifisch Einstellungen vornehmen. Wenn ich z.b. von einer DSL-Leitung mich auf Uni-Rechnern einloggen möchte, ist eine gzip Kompression sinnvoll, der Hostname ist zu lang, die Verbindung zum Agenten soll weitergereicht werden, X soll weitergeleitet werden und der Nutzername ist auch ein anderer. Die Kommandozeile würde lauten:
ssh -X -A -C ringehah@sshproxy.hrz.tu-freiberg.de
Wenn ich nun aber diesen Text in der ~/.ssh/config stehen hab:

Host sshproxy
HostName sshproxy.hrz.tu-freiberg.de
User ringehah
ForwardAgent yes
Compression yes
ForwardX11 yes

dann verkürzt sich die Kommandozeile auf ssh sshproxy - schick, oder?

]]>
http://martin.ringehahn.de/shellblog/?feed=rss2&p=121
Lektion 4: Ausgabeumleitung und Pipes http://martin.ringehahn.de/shellblog/?p=120 http://martin.ringehahn.de/shellblog/?p=120#comments Fri, 10 Oct 2003 15:51:40 +0000 chrono http://martin.ringehahn.de/shellblog/?p=120 Die ganzen vielen kleinen Programme nutzen ja “allein” wenig. Man muss das ganze ja verknüpfen können. Das möchte ich nun hier behandeln Ich werde anhand von einem Beispiel erläutern, wie die Konzepte anzuwenden sind. Die Theorie dahinter wird dabei auch gleich offensichtlich. Als gutes Beispiel dienen z.b. Apache (Webserver) LogDateien. Ein Standartformat dieser Dateien ist: Einzelne Zugriffe zeilenweise, Details spaltenweise:
ip - (nutzer) - datum - anfrage - antwortcode - gesendete bytes - referrer - useragent
Beispiel:
p3e9bbd6d.dip.t-dialin.net - - [10/Oct/2003:16:11:26 +0200] “GET /shellblog/index.rdf HTTP/1.1″ 304 - “-” “Mozilla/5.0 (compatible; MSIE 6.00; Windows 98)”
nun möchte ich aus dieser (derzeit circa 250000 Zeilen umfassenden) Datei folgende Information auslesen: die Referrer im Oktober 2003, für das shellblog (in dem Logfile steht alles von martin.ringehahn.de), sortiert, keine internen Referrer und keine doppelten Einträge. Mit dem > Symbol kann ich die Bildschirmausgabe (Standartausgabe) eines Befehls in eine Datei umleiten. z.b. schreibt der Befehl cat datei1 > datei2 den Inhalt der Datei 1 in Datei 2. Eventuelle Fehlermeldungen landen nicht in der Datei, da die Fehlerausgabe (StandartError) einen anderen “Kanal” verwendet und weiterhin auf dem Bildschirm erscheint. Wenn wir unsere Aufgabe mit diesem Konstrukt lösen wollen, kommt ungefähr so etwas dabei raus (die Originaldatei heisst “accesslog”, alles hinter und inkl. ‘#’ sind Kommentare von mir):

grep shellblog accesslog > datei1 # nur Zeilen, welche 'shellblog' enthalten
grep Oct/2003 datei1 > datei2 # davon nur Einträge von Oktober 2003
awk '{print $11}' datei2 > datei3 # die elfte Spalte beinhaltet den Referrer
grep http datei3 > datei4 # nur http-Adressen. damit fallen Leereinträge auch raus.
grep -v ringehahn datei4 > datei5 # keine internen Referrer, alles mit 'ringehahn' fliegt Raus
sort datei5 > datei6 # schoen alphabetisch Sortieren
uniq datei6 > datei7 # doppelte Einträge fliegen Raus.

Man kann jetzt die Dateien 1 bis 7 anschauen und sieht schön, was welches Programm gemacht hat. Dummerweise interessieren uns die Dateien 1-6 für das Endergebnis herzlich wenig. Ausserdem ist es eine höllentipperei, die keiner gern macht. Um nun die Dateien 1-6 überflüssig zu machen kommen die Pipes ins Spiel. Man stelle sich vor, dass das eine Programm seine Ausgabe direkt an das nächste weiterreicht. In den Manpages tauchen oft die Begriffe “standard input” und “standard output” auf. grep manpage: “grep searches the named input FILEs (or standard input if no files are named, or the file name - is given)”. Das Prinzip hat schon einige Jahre auf dem Buckel - die Notation wie sie heute verwendet wird, stammt aus der Zeit um 1972. Das Prinzip ist: “alles ist eine Datei”. Es hat sich bewährt. Nun hier die “kurze” und weitaus elegantere Variante (obwohl man vielleicht die “greps” in ein einziges ‘grep’ packen könnte):

grep shellblog accesslog | grep Oct/2003 | awk '{print $11}' | grep http|grep -v ringehahn | sort | uniq > datei1

oder halt ohne das > datei1 um direkt auf den Schirm zu schreiben. Ich möchte behaupten, dass so ziemlich jedes Programm in der shell mit stdin/stdout und pipes arbeiten (kann). Ich erwarte weiterhin, viel mehr sinnreiche Beispiele in den Kommentaren finden zu können :)
Nachtrag [12.10.2003]:
Sollte man mal die Funktionalität von Pipes brauchen auch wenn die Prozesse nicht direkt miteinander aufgerufen werden (können) oder sollte eines der verwendeten Programme nicht mit Stdin umgehen können dann kann man “Named Pipes” verwenden. Prinzip: man erstellt eine spezielle Datei (Named Pipe), ein Prozess schreibt in diese Datei, ein anderer liesst sie. (Kann man mit ein bisschen Feinarbeit auch verwenden um z.B. dynamische Konfigurationsdateien zu implementieren) Beispiel: Pipe erstellen:

mknod /tmp/neuepipe p

oder

mkfifo /tmp/neuepipe

um diese dann zu verwenden: cat accesslog > /tmp/neuepipe & Das Kaufmannsund dient dazu, dass dieser Prozess in den Hintergrund wandert. Hier sieht man, dass das Kommando nichts “direkt” in die Datei schreibt:

prw-r--r--  1 chrono  wheel  0 Oct 12 15:31 /tmp/neuepipe
0 Bytes in der Datei. Wenn ich jetzt diese Datei lese (z.b. mit cat /tmp/neuepipe) dann wird die Pipe “gestartet”, das eine cat “schreibt” hinein, das andere liesst aus. Wenn der erste Befehl “fertig” ist, schickt es ein “Datei ist zuende” (EOF) in die Datei und beendet sich, das andere cat beendet sich dadurch dann auch. Unter cygwin kann man jedoch derzeit keine named Pipes erstellen.

]]>
http://martin.ringehahn.de/shellblog/?feed=rss2&p=120