Seite wählen

NETWAYS Blog

Administrators Toolbox: Die Zsh

Einfuehrung

Zu jeder stereotypischen Hacking-Szene in einem Film oder einer Serie gehoert das Terminal in dem kryptische Ausdruecke, Befehle oder Programmcode ueber den Bildschirm huschen. Je nach Ausfuehrung ist das unterschiedlich laecherlich, aber nichtsdestotrotz ist das Terminal seit seiner Einfuehrung als Nutzerinterface eine der wichtigsten Schnittstellen zwischen Mensch und Maschine geblieben. Entstanden aus dem Wunsch und der Notwendigkeit mit einem Programm zur Laufzeit zu interagieren, war es ein langer Weg von den umfunktionierten elektrischen Schreibmaschinen (Teletype) ueber 80×25 Zeichen Monochrom-Roehrenmonitore (wahlweise in gruen oder orange) bis hin zu einem Terminal-Emulator als ein weiteres Fenster in der graphischen Oberflaeche.

Dialogisch mit dem System zu interagieren und mit vergleichsweise kleinen Anforderungen beliebig komplexe Prozesse anzustossen eroeffnen einem viele Moeglichkeiten und, nach Meinung des Autors, sind in vielen Anwendungen noch keine Alternativen in Sicht, die es besser machen wuerden. Mit Text als menschenverstaendliche Schnittstelle dient dienen Shell als eine Abstraktionshuelle fuer das Betriebssystem und andere Anwendungen, die einem zumindest auf Unix-aehnlichen Systemen noch sehr haeufig begegnet.

Der haeufig anzutreffende Platzhirsch in dem Feld der Shells ist die bash, die Bourne again shell, zumindest auf vielen gaengigen Linux-Distributionen und ist als solides und maechtiges Werkzeug bekannt. An manchen Stellen lassen sich jedoch ein paar Schwaechen finden und manchmal ein gewisser Komfort vermissen, gerade bei der Interaktion mit dem eigenen Desktop-System, deshalb wird hier eine Alternative thematisiert, die Z shell (kurz zsh). Die Geschichte, der Code und tiefere technische Details sollen hier nicht im Zentrum stehen, eher die konkrete Nutzung und einzelne Features.

Installation

Wie die Installation auf dem jeweiligen System verlaeuft haeng natuerlich von der Umgebung ab, auf Linux duerfte der jeweilige Packetmanager diesem Zweck dienen, hier reicht ein apt-get install zsh, aber your mileage may vary. Im Zweifelsfall kann man die entsprechenden Dateien auf der offiziellen Seite finden.

Konfiguration

Der wichtigste Teil an der Benutzung der zsh duerfte die Konfiguration sein, da sich eine Unmenge von Parametern veraendern lassen und viele der Features aktiviert/konfiguriert werden muessen. Fuer die Ungeduldigen gibt es eine Beispielkonfiguration, die im Folgenden Schritt fuer Schritt nachvollzogen wird. Ansonsten kann die zsh auch ohne Konfiguration gestartet werden, sie wird den Benutzer auf diesen Fakt hinweisen und Empfehlungen bezueglich des weiteren Vorgehens liefern. Auch liefern Distribution typischerweise eine Basiskonfiguration mit und die Suchmaschine der persoenlichen Wahl duerfte schnell ein Vielzahl von weiteren Beispielen und Anleitungen bieten. Am Ende dieses Beitrags sind auch noch einige Links als Startpunkt beigefuegt. Natuerlich sind auch die man-pages ein sinnvoller Anlaufpunkt.

Keybindings/Tastenkombination

# Use Vi(m) style key bindings.
bindkey -v

Die ist eine sehr minimale Konfiguration und weist die zsh an, vim-artige Tastenkombination zu verwenden. Dies ist eher minimal, Aktionen zur Navigation innerhalb der Eingabezeile und vieles mehr koennten hier konfiguriert werden.

Prompt

Die Prompt (also der Text, der vor jeder Eingabezeile steht) kann gut zur Darstellung von nuetzlichen Informationen genuetzt werden oder sollte mindestens huebsch sein.

[[ "$COLORTERM" == (24bit|truecolor) || "${terminfo[colors]}" -eq '16777216' ]] || zmodload zsh/nearcolor
autoload -Uz colors && colors

Zuerst wird versucht die Faehigkeiten des Terminal bezueglich der Darstellung von Farben zu bestimmen und die entsprechenden Module geladen

autoload -Uz promptsubst
autoload -Uz promptinit && promptinit
autoload -Uz vcs_info

Einige weitere Module, die die Personalisierung der Prompt ermoeglichen.

# Define the theme
prompt_mytheme_setup() {
local user
if [[ $USER == "root" ]] then
user="%F{9}%n"
else
user="%F{12}%n"
fi
if [[ ! -z $SSH_CLIENT ]] then
user="%F{3}SSH -> $user"
fi

Hier wird ein eigenes Theme begonnen, dass einen normalen Nutzer in einer Farbe darstellt und den Nutzer „root“ in einer anderen.
Zusaetzlich wird angezeigt, ob man ueber SSH verbunden ist.

# Information about version control systems
zstyle ':vcs_info:*' enable git
zstyle ':vcs_info:*' check-for-changes yes
zstyle ':vcs_info:*' use-prompt-escapes yes
zstyle ':vcs_info:*' formats "%s - (%r|%b)" "%u%c"
local prefix="%(?..[%?%1v] )"
local vcs="%(2v.%U%2v%u.)"
PROMPT="%K{0}%F{9}$prefix%f%B$user@%M%f %F{7}%/%b%f%k
%B#%b %E"
RPROMPT="%K{0}%F{9}$vcs%f%k"
add-zsh-hook precmd prompt_mytheme_precmd
}

Die Prompt wird zusammengesetzt und um Information ueber git-Repositories ergaenzt, falls das aktuelle Arbeitsverzeichnis sich in einem solchen befindet.

prompt_mytheme_precmd () {
setopt noxtrace noksharrays localoptions
local exitstatus=$?
local git_dir git_ref
psvar=()
[[ $exitstatus -ge 128 ]] && psvar[1]=" $signals[$exitstatus-127]" || psvar[1]=""
vcs_info
[[ -n $vcs_info_msg_0_ ]] && psvar[2]="$vcs_info_msg_0_"
}

Vor jeder Promptdarstellung wird der EXITSTATUS des vorherigen Programms ueberprueft und angezeigt, falls dieser !=0 (Fehler) ist.

# Add the theme to promptsys
prompt_themes+=( mytheme )
# Load the theme
prompt mytheme

Die Prompt wird geladen.

Noch einige Optionen

setopt nobeep
Deaktiviere die Terminal-„Glocke“.

setopt autocd
Die Eingabe eines Verzeichnisnamens wird als „cd $VERZEICHNIS“ interpretiert.

# Prevent overwriting existing files with '> filename', use '>| filename'
# (or >!) instead.
setopt noclobber

Verhindere versehentliches Ueberschreiben von Dateien durch Redirection.

# Enable zsh's extended glob abilities.
setopt extendedglob

Erweitertes globbing.

setopt longlistjobs
Bei der Ausgabe von jobs wird die PID mit angezeigt

Autovervollstaendigung

## Initialize completion
autoload -Uz compinit && compinit

# Automatically list choices on an ambiguous completion.
setopt autolist
## show list of tab-completing options
zstyle ':completion:*:default' list-prompt '%p'
## cache completion for re-use (path must exist)
zstyle ':completion:*' use-cache yes; zstyle ':completion:*' cache-path
## _complete -> completiong
## _expand -> expand variables
## _prefix -> ignore everything behind cursor
## _approximate -> fuzzy completion
## _ignore -> ignore some matches (i.e. directories when doing cd)
zstyle ':completion:::::' completer _expand _complete _prefix _ignored _approximate
## one wrong character every X characters is corrected
## X = 5 is a reasonable default
zstyle -e ':completion:*:approximate:*' max-errors 'reply=( $(( ($#PREFIX + $#SUFFIX) / 5 )) )'
## correct lowercase to uppercase
zstyle ':completion:*:(^approximate):*' matcher-list 'm:{a-z}={A-Z}' # Kleinschreibung automatisch zu Grossschreibung korrigieren.
## keep magic prefixes like '~' when expanding
zstyle ':completion:*:expand:*' keep-prefix yes
## compelte a/b/c zu abc/bcd/coo
zstyle ':completion:*' list-suffixes yes
## colors in completion menu ##
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
# allow autocomplete-navigation with arrowkeys
zstyle ':completion:*' menu select #enable a menu which can be browsed with arrow keys
# tab completion after pressing tab once (default is twice)
setopt nolistambiguous
# allow in word completion
setopt completeinword

Diverse Einstellungen zur Autovervollstaendigung, unter anderem die Darstellung der validen Optionen und Vervollstaendigung in Woertern.

History/Geschichte

Gerade bei der Historie ist der Nutzen der zsh am deutlichsten, so koennen Befehle ohne grosse Umwege direkt nach Eingabe in die Historie geschrieben werden, ohne dass grosse Umwege beschrieben werden wie es bei der bash normalerweise noetig waeren.

# write command to historyfile imediatelly
setopt appendhistory
setopt incappendhistory
## max size and location of history-savefile
STSIZE=20000
SAVEHIST=20000
if [[ ! -a ~/logs ]] {
mkdir ~/logs
}
HISTFILE=~/logs/zshhistory.log
## no duplicated commands
setopt histignoredups
## no emptylines
setopt histignorespace
# Fancy search for history. Install peco
if ! [ -x "$(command -v peco)" ]; then
bindkey '^R' history-incremental-pattern-search-backward
else
## bind peco to ctrl-R as a better reverse search than the buitin if it is available
reverse_search(){print -z "$(tac ${HISTFILE} | peco)"}
zle -N rs_peco reverse_search
bindkey "^R" rs_peco
PECO=/usr/bin/
fi

Zusaetzlich wird hier das Programm peco fuer die Suche in der Historie verwendet (falls vorhanden). Dies stellt die passenden Eintraege sehr schnell und sichbar dar.

Gemischtes

umask 077
Stellt die umask sehr restriktiv ein. Dateien muessen dann erst fuer andere lesbar gemacht werden.

LS_COLORS=$LS_COLORS:'di=0;35:'; export LS_COLORS
Farbschemata fuer ls.

if [[ -f ~/.config/zsh/aliases ]]; then
source ~/.config/zsh/aliases
fi

Lese Aliase aus der Datei ~/.config/zsh/aliases, falls vorhanden.

export EDITOR=nvim
Setze neovim als Standart-Editor fuer die Umgebung.

if [[ -d ~/scripts ]] {
export PATH=$PATH:~/scripts
}

In ~/scripts sind selbst erstellte Skripte des Nutzers und werden hiermit direkt nutzbar.

man() {
env \
LESS_TERMCAP_mb=$(printf "\e[1;31m") \
LESS_TERMCAP_md=$(printf "\e[1;31m") \
LESS_TERMCAP_me=$(printf "\e[0m") \
LESS_TERMCAP_se=$(printf "\e[0m") \
LESS_TERMCAP_so=$(printf "\e[1;44;33m") \
LESS_TERMCAP_ue=$(printf "\e[0m") \
LESS_TERMCAP_us=$(printf "\e[1;32m") \
man "$@"
}

Dies faerbt man-pages ein und macht sie dadurch leichter lesbar.

Aliase

Aliase sind frei konfigurierbare „Pseudokommandos“ die durch die zsh ausgewertet und durch die richtigen Kommandos ersetzt werden. Dies bietet sich meistens fuer haeufig gebrauchtet Kommandos an.
alias ll="ls -llh --color=auto" ist ein gutes (und haeufiges) Beispiel dafuer.
Damit kann die detailierte Ansicht von ls direkt und ohne Tippen der Optionen benutzt werden. Beispiele fuer nuetzliche Aliases sind vielerlei zu finden, aber ein guter Ansatz ist immer die Frage, welche Kommands haeufig benoetigt werden und die daher sinnvoll abgehkuerzt werden koennten.

Fuer Tippfaule bietet es sich an, haeufige Befehle stark abzukuerzen, etwa alias v="vim" oder alias g="git".

Noch mehr „Features“

  • zsh kann nativ sockets und  TCP-Verbindung oeffnen, man kann also ohne weiteres (simple) Netzwerkkommunikation damit (warum auch immer) (zsocket bzw. ztcp)
  • Auch FTP ist nativ vorhanden, falls man nur kurz einen FTP-Client braucht (zftp)
  • Auch eingebauter Kalender ist ist vorhanden (cal)

Abschluss und Weiterfuehrendes

Alles hier ist nur ein kleiner Einblick in die Moeglichkeiten und Konfigurationen und erhebt auf keinen Fall einen Anspruch auf Vollstaendigkeit. Falls weitergehendes Interesse besteht, sind noch ein paar Links angehaengt, die mindestsens mal als Einstieg dienen. Natuerlich sind Korrekturen und Vorschlaege hier erwuenscht und koennen gerne in den Kommentaren oder auf anderem Weg uebermittelt werden. Damit bleibt fuers Erste nur noch der Leserin Spass beim Experimentieren zu wuenschen und vielen engagierten Bastlern zu danken, die zum Einen das Alles gebaut haben, aber auch Beispiele und Dokumentation bereitstellen.

Froehliches Shell-Hacken 🙂

Lorenz Kästle
Lorenz Kästle
Systems Engineer

Lorenz hat seinen Bachelor der Informatik an der FAU gemacht und sich zuletzt mit Betriebssystemen dort beschäftigt. In seiner Freizeit beschäftigt er sich ein wenig mit XMPP und der Programmiersprache Erlang.

Zurück in die Zukunft: Icinga2-Benachrichtigungen mit XMPP

Der klassische Weg um Benachrichtigung an Nutzer zu verschicken ist bei Icinga 2 (wie bei so vielen anderen Systemen auch) das Versenden einer Email. Für zeitnahe und mobilere Benachrichtigung gibt es den Versands von SMS, Sprachanrufe oder andere Optionen.

Mit dem Aufkommen und der starken Verbreitung von Chat-Diensten ist die Einbindung eines solchen Benachrichtigungsfunktion der offensichtliche nächste Schritt (oder zumindest eine tolle Spielerei). So gibt es Skripts für Slack Rocket Chat, Matrix, Telegram, selbstverständlich IRC und gerüchteweise auch Iridium. Wie man aus der Überschrift entnehmen kann geht hier es hier dann um einen weiteren Dienst, nämlich XMPP/Jabber (Jabber ist der alte Name des Protokolls).

XMPP ist ein freier Standard, erweiterbar und es gibt zahlreiche Implementierungen für Server und Clients. Der allgemeine Bekanntheitsgrad ist eher gering, obwohl der Einsatzbereich sehr groß ist. Zahlreiche größere Internetfirmen haben ihre Nachrichtenaustauschfunktionalität zu Beginn schlicht auf XMPP aufgebaut und mit freier Software umgesetzt (und dann natürlich einen „walled garden“ um die Nutzer gebaut). Die Kommunikation verläuft ähnlich wie Email, ein Client (ein Nutzer bzw. sein(e) Endgerät(e)) verbindet sich mit einem Server und übergibt diesem eine Nachricht; diese wird dann zu dem Zielserver transportiert, welcher sie dann an den Empfänger weiterleitet. Ähnlich wie bei Email ist es ein föderiertes System, prinzipiell kann jeder sich einen XMPP-Server aufsetzen und mit allen anderen reden. Dementsprechend wird ein Nutzer auch durch eine JID identifiziert, die aus einem Nutzername und einem Domänenteil in der Form nutzer@domaene.tld besteht.

Es gibt nun drei Gründe für die Benachrichtigung via XMPP:

  1. Ganz generell ist ein zweiter Kanal sinnvoll, da der erste Kanal ausfallen kann. Sollte das Mailsetup ausfallen, kann niemand darüber per Email benachrichtigt werden und natürlich wären alle weiteren Benachrichtigungen ebenfalls nicht mehr möglich.
  2. XMPP ist ein sehr mächtiges vielfältiges Protokoll und kann einen Nutzer zeitnah auf einem quasi beliebigen Endgerät erreichen (vorausgesetzt dieses Endgerät ist in irgendeiner Form online, Stichwort: PUSH-Nachrichten). Zusätzlich kann eine XMPP-Infrastruktur in einer beliebigen Größenordnung selbst betrieben werden ohne sich weitere externe Abhängigkeiten ins Haus zu holen.
  3. Der Autor dieses Artikel ist ein XMPP-Fan und würde gerne ein wenig Werbung dafür machen. Auch als Alternative zu den populären proprietären IM-Lösungen fragwürdiger Unternehmen.

Was die Umsetzung angeht, so gibt es hier schon genug Vorlagen, unter anderem diesen Artikel aus gleichem Hause, welcher das Thema zwar abdeckt, aber nach sechs Jahren doch auch ein Update verdient. Zwei Punkte bedürfen im besonderen einer Aktualisierung:

  1. Der Wechsel von Python2 auf Python3
  2. Die eingesetzte XMPP-Bibliothek hat etwas Rost angesetzt

Aus diesem Grund wurde auch diese Variante entwickelt, aber die Verwendung von Umgebungsvariablen für die Übergabe von sensiblen Daten ist im Moment bei der Verwendung des Directors nicht möglich. Zusätzlich wird die sleekxmpp-Bibliothek mittlerweile nicht mehr weiterentwickelt oder gewartet. Diese und weitere Anpassungen  wurden in diese Version  integriert um die sich dann auch dieser Artikel dreht.

Wenn man nun XMPP-Benachrichtigungen von dem eigenen Icinga 2-System erhalten möchte, benötigt man vorher schon die Möglichkeit XMPP-Nachrichten zu versenden, also mindestens einen Account bei einem Anbieter entsprechender Infrastruktur, beispielsweise einer von conversations.im oder jabber.at. Alternativ kann auch eine eigene Infrastruktur erstellt werden. Zur Installation des Skriptes müssen zuerst die Abhängigkeiten erfüllt werden, was in den meisten Fällen durch die Installation von Python3 mit Standardbibliotheken und der Bibliothek slixmpp abgeschlossen sein sollte. Dann muss das Skript selbst an einen passenden Ort kopiert werden und die Konfiguration aus dem Ordner icinga2_config in die eigene Konfiguration integriert werden. Besonders ist hier natürlich das Eintragen des Pfads zum Skript, dem|den eigenen XMPP-Account(s) (sowohl des Senders als auch des Empfängers) und des Passworts. Alternativ kann die Konfiguration auch mit dem Director erstellt werden.

Das ganze sieht dann beispielsweise in Conversations so aus:

Das Ganze ist noch recht minimalistisch und hilfreiche Ideen|Vorschläge|Kritik sind herzlich willkommen. Dann bleibt an dieser Stelle nicht viel mehr übrig als zu hoffen, dass dies hier jemandem nützt, was übrigens auch gerne mal kurz als Feedback gegeben werden kann 🙂

Lorenz Kästle
Lorenz Kästle
Systems Engineer

Lorenz hat seinen Bachelor der Informatik an der FAU gemacht und sich zuletzt mit Betriebssystemen dort beschäftigt. In seiner Freizeit beschäftigt er sich ein wenig mit XMPP und der Programmiersprache Erlang.

NETWAYS stellt sich vor – Lorenz Kästle

This entry is part 8 of 63 in the series NETWAYS stellt sich vor

 

Name: Lorenz Kästle

Alter: 28

Position bei NETWAYS: Consultant

Bei NETWAYS seit: Juni 2020

 

 

 

Wie bist du zu NETWAYS gekommen und was genau gehört zu Deinem Aufgabenbereich bei NETWAYS?

Ich wollte nach dem Studium etwas Sinnvolles machen und der Open Source-Ansatz von Netways schien mir da passend zu sein.
Auf diese Weise leiste ich vielleicht einen kleinen Beitrag zur Verminderung des riesigen Bergs an proprietärer Software.

Als Consultant betreue ich Kunden und richte die Softwarelösungen
bei Kunden ein und passe sie an die jeweiligen Bedürfnisse an.
Zusätzlich wird den Kunden der Umgang mit den Programmen vermittelt.

 

Was steht bei dir gerade an?

Ich bin noch in der Anfangsphase und lerne gerade alles kennen was ich für die künftige Arbeit bei NETWAYS benötige.

 

Was machst Du, wenn Du mal nicht bei NETWAYS bist?

Ein wenig mit der eigenen Infrastruktur basteln und etwas an der
langen Liste von ToDos knabbern

 

Wie geht es in Zukunft bei Dir weiter?

¯\_(ツ)_/¯

Lorenz Kästle
Lorenz Kästle
Systems Engineer

Lorenz hat seinen Bachelor der Informatik an der FAU gemacht und sich zuletzt mit Betriebssystemen dort beschäftigt. In seiner Freizeit beschäftigt er sich ein wenig mit XMPP und der Programmiersprache Erlang.