Skip to content
This repository has been archived by the owner on Mar 31, 2021. It is now read-only.

Latest commit

 

History

History
377 lines (289 loc) · 12.3 KB

meetup.asciidoc

File metadata and controls

377 lines (289 loc) · 12.3 KB

bash Meetup

env

USER="schiermi"
NAME="Andreas Schiermeier"
EMAIL="[email protected]"
TWITTER="@schiermi"
EMPLOYER="FactSet Digital Solutions GmbH"
_=("🐧@💻" "🚴" "https://ccc-ffm.de/")

Shells (sh, ksh, bash, zsh)

Was ist eine Shell, bash

  • lt. man 1 bash ein "command language interpreter"

    • "Programmiersprache für Betriebssystemprozesse"

    • direkte Kommandoeingabe (interaktive Shell)

    • Kommandos nach einem "Drehbuch" (Shellskript).

Interaktiv kann der Bediener auf unvorhergesehene (Fehler) reagieren. Passiert im Script zuviel Unbedachtes muss öfters gedreht oder dass Drehbuch werden.

Geschichte

  • Anfang der 1970er Jahre: Unix-Shells

  • Ende der 1970er: Stephen R. Bourne Shell, sh, Basis aktueller UNIX-shells; sowie ksh, csh

  • Ende der 1980er: bash bourne again shell vereint und erweitert bekannte Features

  • Anfang der 1990er: zsh, weitere neue Ansätze, werden teilweise auch in bash übernommen

  • Aktuell: bash auf vielen Systemen verfügbar und die Standardshell; Geschichte "erlebbar"

Usability (im interaktiven Betrieb)

  • Vorraussetzung & Einstiegshürde: Kommandos müssen bekannt sein

  • ; (Semikolon): separiert mehrere Anweisungen in einer Eingabezeile

  • ⏎ (Zeilenschaltung, newline): Bringt Anweisungen zur Ausführung

  • einige (wichtige) Tastenkombinationen mit ✲ (Strg, Steuerung, Ctrl, Control)

✲+C

Eingabe oder Programmausführung abbrechen (genauer: sendet Signal 2, SIGINT)

✲+D

Sende EOF (beende die Eingabe)

✲+R

In der Befehlszeilenhistorie suchen

✲+S

Terminal Flusskontrolle Stopp

✲+Q

Terminal Flusskontrolle Fortsetzen

✲+Z

Vordergrundprogramm in interaktiver Shell mit Jobcontrol anhalten (sende Signal 19, SIGSTOP)

✲+A

Springe in der Befehlszeile an den Anfang (via readline)

✲+E

Springe in der Befehlszeile an das Ende (via readline)

← →

Innerhalb der Befehlszeile navigieren

↑ ↓

Innerhalb der Befehlszeilenhistorie navigieren

Note
Unter Umständen werden Tastenkombinationen vom Betriebssystem, der grafischen Benutzeroberfläche oder dem Terminalemulator abgefangen. Desweiteren können Terminal (tty) oder die readline Bibliothek abweichend arbeiten

Kommandos: Programme

Programme sind per Dateisystempfad vom Betriebssystem auffindbar und werden diesem zur Ausführung überlassen.

  • /bin/ls

  • /bin/mv

Kommandos: Builtins

Builtins sind aus Effizienzs- oder Machbarkeitsgründen von der Shell selbst abgearbeitete Befehle.

Effizienz
  • pwd

  • test

  • [

  • (time)

Machbarkeit
  • cd

  • read

  • return

  • exit

  • [[

  • builtin

  • command

Siehe auch
  • man 1 bash, SHELL BUILTIN COMMANDS

  • help

  • help builinname

Kommandos: Funktionen

Funktionen fassen mehrere Kommandos als benannte Subroutine zusammen (vergleichbar zu Programmiersprachen).

Definition
function fname () {
  echo "Mein Name ist ${FUNCNAME}."
  return 0
}
Welche Funktionen gibt es?
declare -F
…inkl. Definition?
declare -f

Kommandos: Aliase

Aliase dienen als Abkürzung für häufig genutzte Aufrufe.

# Eingabe von "la" führt "ls -la" aus
alias la='ls -la'

# Eingabe von "cd.." führt "cd .." aus
alias cd..='cd ..'

# Aliase auflisten
alias

# Alias löschen
unalias la

Suchreihenfolge: Alias, Funktion, Builtin, Programm (Suche anhand PATH)

Siehe auch
  • man 1 bash, "COMMAND EXECUTION"

Variablen & Arrays - Deklaration, Zuweisung

variable='inhalt'

Deklaration bei erster Zuweisung

declare variable

Deklaration ohne Zuweisung

declare variable='inhalt'

declare -i variable=1542650400

Ganzzahl, Zuweisung einer Zeichenkette ergibt 0!

declare -ri c='299792458'

Ganzzahl, readonly

unset variable

Variable löschen

declare -a indexarray=( 'Stickstoff' 'Sauerstoff' 'Rest' )

Indiziertes Array (Startindex: 0)

declare -A keyarray=( ['VW']='Abschalteinrichtung' ['Frankfurt']='Stimmenzählung' )

Textindiziertes Array

unset array

ganzes Array löschen

unset array[index]

Wert an Index in Array löschen

Note
Innerhalb von Funktionen zur Begrenzung des Gültigkeitsbereichs local statt declare verwenden.

Variablen & Arrays - Verwendung

einfache Variablen
  • Zugriff auf einfache Variablen: $variable

    • …oder besser: ${variable}

Arrays
  • Zugriff auf das zweite Element des Arrays (Index 1): ${indexarray[1]}

  • Alle Elemente: ${indexarray[@]}

  • Anzahl der Elemente: ${#indexarray[@]}

textindizierte Arrays
  • Zugriff auf Element des Index "key": ${keyarray["key"]}

  • Alle Keys: ${!keyarray[@]}

  • Alle Elemente: ${keyarray[@]}

Beispiele
echo "${HOME}"
echo "${indexarray[1]}"
echo "${keyarray["Frankfurt"]}"

"besondere" Variablen

$0

Scriptname

$#

Anzahl der übergebenen Parameter

$1, `$2, … $9

dem Script übergebene Parameter

${10}, ${11}, …

dem Script übergebene Parameter (> 9)

$*

dem Script übergebene Parameter als String verbunden

$@

dem Script übergebene Parameter als Array

$$

Prozess-ID der Shell

$?

Fehlercode des zuletzt beendeten Programms

${PPID}

Prozess-ID des Elternprozesses

${HOSTNAME}

Hostname des das Script ausführenden Systems

${PWD}

aktuelles Arbeitsverzeichnis

${HOME}

Hauptverzeichnis des angemeldeten Benutzers; Ziel für "cd" und Wert von ~

${PATH}

Suchpfad für ohne vollen Pfad aufgerufene Programme

"besondere" Variablen - PATH

Beispiel "ls"

PATH="/home/as/bin:/usr/local/bin:/usr/bin:/bin:/usr/lib/mit/sbin"

Suche nach (erster Treffer "gewinnt"):
  • /home/as/bin/ls

  • /usr/local/bin/ls

  • /usr/bin/ls

  • /bin/ls

  • /usr/lib/mit/sbin/ls

"Suchergebnis" wird für die Laufzeit der Shell vermerkt!
  • Suchcache anzeigen: hash -l

  • Suchcache leeren: hash -r

Siehe auch
  • man 1 bash, PARAMETERS

Parametertrennung - IFS

Noch eine Variable mehr: IFS

  • ${IFS}: Internal Field Separator

  • Trennzeichen für die "Generierung" von Parametern aus Variablen.

  • Standard: Leerzeichen, Tabulator, Zeilenumbruch

  • unset IFS stellt den Standard wiederher (nicht: IFS="").

Note
Das erste Zeichen aus IFS wird bei "$*" als Verbindungszeichen der Elemente verwendet.
  • Demo: demo/params.sh

Platzhalter & Textersetzung in Kommandos - Variablen

Allgemein: Textersetzungen im eingegebenen oder eingelesenen Kommando.

  • Es wird etwas Anderes ausgeführt als eingegeben.

Variablen bereits bekannt
echo "${HOME}"

Platzhalter & Textersetzung in Kommandos - Wildcards

Wildcards (üblicherweise anhand von Dateinamen)

*

keines bis beliebig viele Zeichen

?

exakt ein beliebiges Zeichen

[0-9]

ein Zeichen aus dem angegebenen Bereich

  • Wildcards sind kombinierbar

  • Nicht mit RegEx z.B. “grep” (regulären Ausdrücken verwechseln)!

ls -l [0-9]*.csv

Platzhalter & Textersetzung in Kommandos - Berechnungen, Klammererweiterung

Berechnungen via $…
i=2
echo $(( i + 2 ))
Klammererweiterung via Zeichenbereiche z.B.: {2000..2018}{01..12}{a..f}.txt
echo {2000..2018}{01..12}{a..f}.txt

Platzhalter & Textersetzung in Kommandos - Prozesssubstitution, ~

Prozesssubstitution Ausgabe (STDOUT) von anderen Programmen als Parameter nutzen
echo "Externe IP: $(curl -s ifconfig.co)"

# veraltet, nicht verschachtelbar:
echo "Externe IP: `curl -s ifconfig.co`"

# ähnlich: Dateiinhalt als Parameter nutzen
echo "$(< /etc/passwd)"
~
# Wert von ${HOME}
echo ~
# HOME-Verzeichnis eines (anderen) Benutzers
echo ~root

Ausgabeumleitung, Pipes

cmd1 | cmd2

STDOUT von cmd1 mit STDIN von cmd2 verbinden

cmd1 |& cmd2

STDOUT und STDERR von cmd1 mit STDIN von cmd2 verbinden

cmd > datei

STDOUT von cmd datei schreiben

cmd >> datei

STDOUT von cmd an datei anhängen

cmd < datei

STDIN für cmd aus datei einlesen

cmd1 < <( cmd2 )

STDOUT der Subshell von cmd2 als STDIN für cmd1

  • Demo: demo/stdouterr-echo.sh

  • Demo: demo/stdouterr-ls.sh

Hashbang - der Anfang vom Script

Hintergrund

Im Allgemeinen signalisiert der Hashbang (#!) dem Betriebssystem dass diese Datei nicht als Binärdatei ausgeführt werden kann, sondern ein Interpreter zu Hilfe genommen werden soll.

Mögliche Varianten

#!/bin/bash

eindeutig, bash muss jedoch in /bin vorhanden sein

#!/bin/sh

sollte nicht verwendet werden, wenn bash-Features verwendet werden

#!/usr/bin/env bash

findet bash (oder generell den angegebenen Interpreter auch an ungewöhnlichen Pfaden; benötigt aber im Gegenzug einen Zwischenschritt

Der Anfang vom Script - was sonst noch praktisch ist

Laufzeiteinstellungen - better safe than sorry

set -o nounset

Zugriff auf uninitialisierte Variablen erzeugt einen Fehler

set -o errexit

Nicht abgefangene Fehler (rc != 0) beenden das Script

set -o pipefail

Fehler in Pipes-Ketten werden als Fehler des gesamten Konstrukts gewertet

set -o noclobber

verhindert das Überschreiben bestehender Dateien mit cmd > datei erzwingen mit cmd >| datei

IFS=$'\n\t'

verhindert, dass Leerzeichen als Worttrenner verwendet werden

Tools & Styleguide

https://www.shellcheck.net/

Untersucht Script auf potenzielle Fehlerquellen

https://google.github.io/styleguide/shell.xml

Styleguide für Shellskripte

Der Ende vom Script - Aufräumen!

tmpfile="$(mktemp)"

function cleanup() {
  rm -f "${tmpfile}"
}

trap "cleanup" exit

Tolle Tools

  • xargs

  • tr

  • iconv

  • jq (ggf. glowforge.sh)

EOF

xdg-open "https://github.com/schiermi/bashmeetup/"
echo "[email protected] - @schiermi"
echo "Danke für das Interesse!"
~adt/guest
echo "$?"