#format rst

:title: Shell II: die kleinen Helferlein
:author: Dario & Lars
:css: https://wiki.hack-hro.de/talk_styles/assets/css/style2.css
:description: Hackspace Rostock e.V.
:data-scale: 0.7
:data-transition-duration: 1

----

::

	       ________           ________
	     /  ______  \       /  ______  \
	   /  /        \  \   /  /        \  \
	 /  /            \  "  /            \  \
	|  |               \ /               |  |
	|  |      ____  _   "      _ _       |  |
	|  |     / ___|| |__   ___| | |      |  |
	|  |     \___ \| '_ \ / _ \ | |      |  |
	 |  |     ___) | | | |  __/ | |     |  |
	  |  |   |____/|_| |_|\___|_|_|    |  |
	    |  |                         |  |
	      |  |                     |  |
		|  |                 |  |
		  |  |             |  |
		    |  |         |  |
		      |  |     |  |
			|  | |  |
			  | | |
			   | |
			    |

----

Shell Workshop II
=================

Ein Hoch auf die kleinen Helferlein!

----

Gestern, heute, morgen
----------------------

* Rückblick (letzter Workshop): Shell steuert Prozesse, Eingaben, Ausgaben ...

* heute: kleine Programme, deren Funktionalitäten sich mit der Shell verknüpfen lassen

* Abschluss (nächster Workshop): Shell-Skripte - sauber und robust (inkl. Substitution & Quoting)

----

Fahrplan
--------

* reguläre Ausdrücke (kleiner Exkurs)

* grep

* sed

* awk

* coreutils & Co.

----

Seid bereit!
------------

* Startet eure Rechner

* Besucht http://pad.hack-hro.de/Shell2-Spass

* später werdet ihr es brauchen ...

----

Reguläre Ausdrücke
==================

* reguläre Ausdrücke != globbing

* Implementierungen sind leicht verschieden

* Meta-Characters

----

Reguläre Ausdrücke - Beispiele
==============================

    ^foo

    ba[rz]

    hello (world|earth)!

----

grep
====

* Suche ein Muster in Textzeilen

* Anwendungen:
    
  * Filterung

  * Prüfung

  * Dateisuche

----

grep - Beispiele
================

    [\t ]state DOWN[\ ]

    ^[0-9]+(\.[0-9]+){3}(/[0-9]+)?$

    [[:space:]]IN[[:space:]]\+SRV[[:space:]]\+[[:digit:]]\+[[:space:]]\+[[:digit:]]

----

sed
===

 * sed => 'stream editor'

 * von '73 bis '74 von Lee E. McMahon in den Bell Labs entwickelt

 * Nachfolger des '71 entwickelten, interaktiven Editors ed

 * eines der frühesten Werkzeuge, das reguläre Ausdrücke interpretieren konnte

 * arbeitet auf 'per Zeilen'-Basis

----

Haben wir auch das wichtigste nicht vergessen?
==============================================

.. code:: shell-session

  sed -n -e '/main[[:space:]]*(/,/^}/p' quelldatei.c | more

----

Grundlegende Kommandos (unvollständig)
======================================

 * a - (append) fügt eine oder mehrere Zeilen an die passende Zeile an

 * c - (change) ersetzt die ausgewählte Zeile durch eine (oder mehrere) neue

 * d - (delete) löscht die passende Zeile

 * i - (insert) fügt eine Zeile vor der Zeile ein auf die regex zutrifft

 * l - (listing) zeigt nicht druckbare Zeichen an

 * p - (print) gibt die Zeile aus

 * r - (read) lese Zeilen aus Datei

 * s - (substitute) ersetze Zeichenfolge in zutreffender Zeile durch eine andere

 * w - (write) schreibe Zeilen in Datei

 * ! - (Negation) wendet die Befehle auf die Zeilen an, auf die regex nicht zutrifft

----

Die Substiution von Zeichenfolgen
=================================

 * Das Substitutionskommando kann noch mit einigen Argumenten ergänzt werden:

     * s/.../.../g - ersetze global (in jeder zutreffenden Zeile der Datei)

     * s/.../.../p - drucke passende Zeilen auf stdout

     * s/.../.../w - tausche Inhalt des Zwischenspeichers mit treffender Zeile

----

Viel verwendete Schalter für sed
================================

* -n - schaltet die Ausgabe des Puffers (Patternspace) aus

* -e - führe mehrere Befehle nacheinander aus, Miniscript in der Kommandozeile ausführen

* -f - führe Datei (sed-script) aus

## sed -n -e 's/[[:space:]]$//' <datei..........leerzeichen am ende von Zeilen löschen

----

//etc/passwd Benutzernamen mit 'Benutzer' ersetzen (vll. auch Benutzer1, Benutzer2..)


----

awk
===

* Interpretierte Programmiersprache mit vielen Ähnlichkeiten zu C

* versteht die gleichen arithmetischen Operatoren wie C

* Verarbeitung von Zeichenketten

* kann man sich als "pseudo C-Interpreter" vorstellen

* in den 70ern entwickelt von A. Aho, B. W. Kernighan and P. Weinberger => Name, Bell Labs

----

Struktur eines awk-Programmes
=============================

.. code:: shell-session

    muster { aktion }

----

* Die Schlüsselwörter BEGIN und END kennzeichnen einen Block von Anweisungen, der ausgeführt werden soll, bevor irgendwelche weiteren Zeilen gelesen werden

.. code:: shell-session

  BEGIN { aktion }
  { noch eine aktion }
  END { aktion }

----

* Feld-Operatoren werden in der Form $n, wobei n eine Zahl ist, geschrieben

.. code:: shell-session

ls -l | awk '{ print $9, "\t", $3 }'

----

* speziell: $0 gibt das gesamte Feld zurück

----

Arithmetische Ausdrücke
=======================

* +, -, *, /, %

* Besonderheit: ein Leerzeichen bedeutet 'hänge die folgende Zeichenkette an'

Welcher Wert wird der Variablen x zugewiesen?

.. code:: shell-session

    x=1+5*2 3

    awk 'BEGIN { x=5+4 5; print x;}'

----

Zuweisungsoperatoren
====================

* += Addiere Ergebnis zur Variablen

* -= Subtrahiere Ergebnis von der Variablen

* *= Multipliziere Variable mit dem Ergebnis

* /= Teile Variable durch das Ergebnis

* %= Modulo Variable durch Ergebnis

----

Relationale Operatoren
======================

* == , != , > , >= , < , <=

----

Reguläre Ausdrücke
==================

* ~  : trifft zu auf /regex/

* !~ : trifft nicht zu auf /regex/

----

Boolean
=======

* && und ||

Unär
====

* !

----

AWK Kommandos
=============

* if ( kondition )  [ else anweisung ]

* while ( kondition ) anweisung

* for ( ausdruck ; kondition ; ausdruck ) anweisung

* for ( variable in feld ) anweisung

* break

* continue

* { [ anweisung ] ...}

* variable=ausdruck

* print [ liste-von-ausdrücken ] [ > ausdruck ]

* printf format [ , liste-von-ausdrücken ] [ > ausdruck ]

* next 

* exit

awk -F: '{ if ($2 == "") print $1 ": hat kein Passwort!" }' </etc/passwd

----

vordefinierte Variablen
=======================

 * Input Field Separator:

     - Kommandozeile awk -F
     - in einem Skript { FS=":"; }
     - bash: IFS
     - standardmäig Leerzeichen

 * OFS - Output Field Separator:

     - Standard: Leerzeichen

----

 * NF - Number of Fields

 * NR - Number of Records

    awk '{ s += $1; } END { print "Summe:", s, "durchschnittl.:", s/NR }' <daten

 * RS - Record Separator

 * ORS - Output Record Separator

 * FILENAME - aktueller Dateiname ( der Datei, die verarbeitet wird )

----

Kleinkram!
==========

----

Einstieg: ls & nl
=================

* ls: Inhalt von Verzeichnissen ausgeben

* nl: Zeilen nummerieren

----

Anknüpfungspunkte
=================

.. code:: shell-session

    ls -l | nl

* Aufgabe: den git-Commits eines Branches aufsteigende Nummern zuordnen

----

Einstieg: date & read
=====================

* date: Datum ausgeben; aktuellen Zeitstempel ermitteln

* read: Zeileninhalt in Variable(n) übertragen

----

Für das Protokoll
=================

.. code:: shell-session

  (
  start_epoch=$(date +%s)
  read beschreibung
  dauer=$(( ($(date +%s) - start_epoch) / 60))
  echo "$dauer $beschreibung" >>spass.log
  )

----

Für das Protokoll
=================

* Aufgabe 1: Ermittle deine gesamte Spassdauer

* Aufgabe 2: Veraendere den Aufruf, auf dass taeglich eine neue spass-Datei angelegt wird

----

Einstieg: find & xargs
======================

* find: Dateisystemobjekte nach Kriterien auflisten

* xargs: Standardeingabe in Parameter umwandeln

----

Mundstopfer
===========

.. code:: shell-session

    find /home -maxdepth 2 -type f -name .xsession-errors -delete
    find /home -maxdepth 2 -type f -name .xsession-errors | xargs rm

----

Mundstopfer
===========

* Aufgabe 1: Sicheres Löschen der Informationen
* Aufgabe 2: keine Fehlermeldung, falls keine Dateien gefunden wurden
* Aufgabe 3: Sicherer Umgang mit Nutzernamen, die einen Zeilenumbruch enthalten

----

Einstieg: df & sort & cut & mailx
=================================

* df: freier und benutzer Speicher von eingehängten Dateisystemen

* sort: numerisches oder alphabetisches Sortieren von Zeilen

* cut: spaltenweise Filtern

* mailx: nicht-interaktiver Mailversand mit vielen Optionen

----

Klaustrophobia
==============

.. code:: shell-session

    df | sed 1d | awk '{ if ($4 < 100000) print $0; }'

----

Klaustrophobia
==============

* Sortierung nach dem verfügbaren Speicherplatz

* Aufgabe: Formulierung als cron-job-taugliche Zeile mit Mailversand bei Speichermangel

----

Einstieg: dd & Funktionen
=========================

* dd: blockweises Lesen und Schreiben

* Funktionen: Sub-Shell für separate Aufgaben

----

Heuhaufen
=========

.. code:: shell-session

  (
    read_byte() { local char=$(dd bs=1 count=1); echo -n "$char"; [ -n "$char" ]; }
    while read_byte; do dd if=/dev/urandom bs=23 count=1; done
  ) 2>/dev/null <geheimnis >versteckt

----

Heuhaufen
=========

* Aufgabe 1: Entschlüssele den Text!

* Aufgabe 2: Vernichte das Geheimnis nach erfolgreicher Versteckung.

----

Einstieg: sleep & head & tail
=============================

* sleep: Wartezeit

* head / tail: führende/abschließende Zeilen ausgeben

----

Prozesspathologie
=================

.. code:: shell-session

  (
    while sleep 5; do
        top -b -n 1 -o "%MEM" | head -12 | tail -5 | sed "s/^/$(date +%Y%m%d%H%M%S) /"
    done >>nirwana.log
  )

----

Prozesspathologie
=================

* Aufgabe 1: Anzeige der aktuellen Zeilen auch auf der Konsole (parallel zum Loggen in der Datei).

* Aufgabe 2: Sicherstellen, dass die Datei auch wirklich geschrieben wird, bevor das System neustartet.

* Aufgabe 3: Ermitteln der Prozesszeile zum Zeitpunkt des maximalen Speicherbedarfs eines Prozesses.

----

Einstieg: ps & who
==================

* ps: Prozesse auflisten

* who: angemeldete Nutzer auflisten

----

Jagd auf Ikarus
===============

.. code:: shell-session

    watch "ps -ef | grep sudo | grep -v grep"

----

Jagd auf Ikarus
===============

* Aufgabe: Wem gehört der Prozess?

----

Einstieg: basename & wc
=======================

* basename: Dateinamen aus einem Pfad extrahieren

* wc: zählen von Zeichen, Worten und Zeilen

Rundungsfehler
==============

.. code:: shell-session

    find ~ -type f | xargs -n 1 basename | wc | awk '{ print $3 / $1 - 1; }'

----

Rundungsfehler
==============

* Aufgabe: Stelle sicher, dass dies auch mit Dateinamen funktioniert, die Zeilenumbrüche enthalten.

----

Übersehene Helfer
=================

* Dateien: cp / mv / rm / rmdir / touch

* Text: cat / cut / join / tr / uniq

* System / Prozesse: chroot / dirname / du / expr / factor / id / nice / printf / pwd / readlink / seq / stat / test / timeout / true / false / uname / uptime