===== How to survive in the shell ===== //Oder was will der blinkende Cursor von mir??// {{ :linux:robox-mit-schild.png?300 |}} ==== Eine kurze Einführung ==== Eine Shell bezeichnet eine Umgebung um it dem Betriebssystem zu interagieren. Im Fall von Unix-artigen Betriebssystemen wie Linux, BSD stellte die Shell lange Zeit die einzige Möglichkeit dar mit dem Rechenwerk zu arbeiten. Aber auch heute noch wo X-Windows ohne Hexerei und stundenlanges Konfigurieren einfach läuft gibt es gute Gründe ohne dieses auszukommen, z.B. weil der Speicherplatz und RAM-Bedarf den Betrieb für das gelegentliche Editieren einer Konfig Datei auf einem embedded System nicht sinnvoll sind und wertvolle Ressourcen belegen. Oder aber auch auf einem Server System wird grundsätzlich kein X-Windows eingesetzt. Einerseits aus den genau gleichen Performance Überlegungen, andererseits weil durch eine Vielzahl zusätzlicher für X-Windows installierter Pakete auch eine Menge an potentiellen Sicherheitsproblemen entstehen. Aus der Geschichte dieser Systeme heraus ist es auch so, dass alle Aspekte eines solchen Betriebssystems primär über eine Shell steuerbar sind, entgegen z.B. voll grafischer Betriebssysteme wie Windows (wo eine grafische Shell verwendet wird) bei dem die Fähigkeit zur Steuerung über die Kommandozeile erst über die Zeit nachgerüstet wurde, mittlerweile aber eine betrachtliche Vollständigkeit erreicht hat. Diese Eigenschaften der Shell kombiniert mit einem sicheren Fernzugriffs-Werkzeug wie ssh bieten demnach für Unix Rechner eine vollständige und umfassende Möglichkeit die Maschine zu fernsteuern und zu fernadministrieren. === Links === * [[wpen>Shell_(computing)|Wikipedia: Shell (en)]] * [[wpde>Betriebssystem-Shell|Wikipedia: Shell (de)]] * [[wpen>Unix_shell|Wikipedia: Unix Shell (en)]] * [[wpen>Comparison_of_command_shells|Comparison of command shells (en)]] ==== Erste Schritte ==== Jede POSIX konforme Shell verfügt über einen Satz eingebauter Befehle die in den Grundzügen identisch funktionieren und aufgerufen werden. Es ist also nicht immer zwingend nötig bash für alles zu verwenden, auch eine schlankere (und sicherere) csh oder dash tut gute Dienste. Mit diesen integrierten Befehlen (und externen Programmen) kann man also auch einfache (oder komplexere) Skripts schreiben, die Abläufe steuern, Webseiten erzeugen, Dateien umkopieren etc. Schauen wir uns exemplarisch mal ein paar dieser Befehle an: ^ Befehl ^ Funktion ^ Bemerkungen ^ | **ls** | Zeigt Inhalt eines Verzeichnisses an | Hat eine Vielzahl an Optionen (//ls --help//) | | **echo** | Gibt auf der Standardausgabe string aus | Variablen in string werden mit ihrem Wert ersetzt (expandiert) wenn keine oder doppelte Anführungszeichen verwendet werden | | **fg** , **bg** , **jobs** | Job Steuerung | Beispiele unten | ==== Job Kontrolle ==== Beispiel für Job Steuerung /usr/local/bin/meinlanglaufendes_programm -x y & Mit dem ''&'' am Ende der Zeile wird das Programm im Hintergrund gestartet, ev. Ausgaben werden aber trotzdem noch angezeigt. Mit ''fg'' (foreground) holt man das Programm wieder in den Vordergrund. Wenn das Programm im Vordergrund ist, kann man es mit ''CTRL+Z'' unterbrechen und auf Wunsch mit entweder ''bg'' (background) im Hintergrund weiterlaufen lassen oder mit fg die Ausführung im Vordergrund wieder aufnehmen. Mit ''CTRL+C'' oder ''CTRL+BREAK'' hingegen weist man einen im Vordergrund laufenden Job an zu beenden. Ein kleines Beispiel dazu: #!/bin/sh # seq Syntax: # seq LAST # seq FIRST LAST # seq FIRST INCREMENT LAST # sleep syntax: # sleep for ix in $(seq 2 2 20); do echo "ix ist $ix" sleep 5 done echo "Fertig"! Wird dieses Skript durch Anhängen von ''&'' beim Aufruf in den Hintergrund geschickt, ist die Ausgabe immer noch sichtbar, aber die Kommandozeile weiter nutzbar. ==== Prozesse kontrollieren ==== Mit **ps** listet man seine eigenen Prozesse, mit **ps -A** auch alle anderen. Mit **kill** kann man Prozessen Signale senden die im POSIX Standard definiert sind, also z.B. beenden, bedingungslos sofort beenden, Konfiguration neu laden etc. **kill -l** listet alle Signal Definitionen, diese können mit Ihrem Namen oder der Nummer verwendet werden: kill -HUP # sendet das Hangup Signal (meist Neuladen der Konfig an kill -0 ; echo $? # Fragt den Prozess Status an (0 = ok) kill -s 9 # beende bedingungslos kill -s SIGKILL # dasselbe kill -9 -1 # beendet alle Prozesse auf die der User Zugriff hat bedingungslos! === Links === * [[http://www.cyberciti.biz/howto/unix-linux-job-control-command-examples-for-bash-ksh-shell/|Bash/KSH Job Control Examples]] * [[http://www.howtogeek.com/107217/how-to-manage-processes-from-the-linux-terminal-10-commands-you-need-to-know/?PageSpeed=noscript|How to Manage Processes from the Linux Terminal: 10 Commands You Need to Know]] Unix-artige Betriebssysteme bestehen per Konzept aus vielen kleinen sehr spezialisierten Hilfsprogrammen, in diesem Beispiel verwenden wir die externen Programme ''sleep'' und ''seq''. Bei vielen was wir an einem Unix-artigen System machen, werden Textdateien gelesen, editiert oder erstellt, deshalb: ==== Ein Texteditor muss her ==== Es gibt ein Unmenge an verschiedenen Text Editoren für die Kommandozeilen Umgebung (eine Shell ist eigentlich einen CLI - ein Command Line Interface). Für welchen man sich für die tägliche Arbeit entscheidet ist Geschmackssache. Da man aber fast überall vi (vim) in einer reduzierten Version auf dem Basissystem antrifft, wollen wir uns diesen mal genauer ansehen. Auch wenn man mit ''vi'' fast alles machen kann, reichen für die normalen Aufgaben eine handvoll Kommandos. === vi Editor === Der Editor wird mit dem zu öffnenden Dateinamen als Argument aufgerufen, z.B.: vi $HOME/meinedatei Wichtig zu verstehen ist vorab, dass vi zwei generelle Modi kennt: - Kommando Modus - Einfüge Modus Nach dem Start des Editors befindet man sich im Kommando Modus. In diesen kommt man immer wieder mit der //ESC// Taste zurück. Navigieren kann man entweder über die Cursor oder aber über die Tasten **h l** (links/rechts) und **j k** (Zeile hoch/runter). Einzelne Zeichen löschen wir im Kommando Modus mit **x**, ganze Zeilen mit **dd**. Mit **i** wechseln wir in den Einfüge Modus __vor__ dem aktuellen Zeichen, mit **a** __hinter__ dem aktuellen Zeichen - wie erwähnt mit ''ESC'' gehts jederzeit wieder in den Kommando Modus. Das reicht bereits für alle notfallmässigen Arbeiten an Konfigurationsdateien oder Startskripts, was noch fehlt sind Befehle zum Speichern und Beenden oder eben nicht speichern und beenden: Mit **:w** speichert man die Datei an der man arbeitet, mit **:q** verlässt man danach den Editor. Das ganze lässt sich natürlich in einen Schritt kombinieren mit **:wq** (Speichern und Beeenden). Will man eine Datei nicht speichern und einfach nur raus aus dem vermaledeiten vi raus ohne was kaputtzumachen: **:q!** (Nicht speichern und nicht lang nachfragen - ich will raus hier). === Links === * [[http://www.atmos.albany.edu/daes/atmclasses/atm350/vi_cheat_sheet.pdf|vi Cheat Sheet]] ==== Dateien aus dem Netzwerk herunterladen ==== Oft werden Updates, Treiber, Programme etc. auf den Desktop geladen und sollen dann auf das Linux System transferiert werden. Am einfachsten geht das wohl mit FileZilla SFTP, dafür muss nur SSH als Dienst auf dem Zielgerät laufen. Warum aber nicht gleich vom Zielgerät selber heunterladen? Hierzu stehen in der Regel zwei Tools in jeder Installation zur Verfügung: **wget** und meist auch **lynx**. Während wget ein reiner URL-Fetcher ist, darauf spezialisiert HTTP(S) und FTP URLs herunterzuladen, so ist lynx ein ausgewachsener Kommandzeilen Browser. Ein kleines Beispiel, wir laden die Arduino IDE für Linux aus einem Terminal oder einer SSH Sitzung direkt auf das richtige Gerät herunter: wget http://downloads.arduino.cc/arduino-1.0.6-linux32.tgz Nun packen wir das heruntergeladene Archiv aus, wir erstellen dazu einen Programm Ordner im eigenen HOME Verzeichnis und entpacken der Ordnung zuliebe dorthin: mkdir $HOME/app; tar -C $HOME/app -xzvf arduino-1.0.6-linux32.tgz ==== root oder sudo? ==== Wann immer möglich sollte man nicht als root arbeiten und nur für die nötigen Befehle den Befehl ''sudo'' verwenden. Die Idee dahinter ist, dass möglichst wenig als SuperUser gearbeitet wird und nur wenn nötig die entsprechenden Rechte genutzt werden. Bei den meisten Systemen darf ein Mitglied der Gruppe ''sudo'' alle SuperUser (root) Privilegien wahrnehmen. Bei einem Ubuntu oder Debian System wird immer der bei der Installation angelegte User in diese Gruppe aufgenommen und kann den Befehl sofort nutzen. Andere User müssen von root oder einem Mitglied der sudo Gruppe in diese aufgenommen werden: sudo adduser neueruser sudo Diese Änderung wird erst nach einem Neu-Anmelden von ''neueruser'' wirksam! Ob man Mitglied in der Gruppe sudo ist, kann man mit diesem Befehl herausfinden: getent group|grep sudo oder einfach groups ==== System neustarten, ausschalten ==== Um ein Unix System geordnet neu zu starten: shutdown -r now oder simpler: reboot Um das System herunterzufahren und auszuschalten: shutdown -h now oder einfacher: halt === Hardcore Reboots... === Wenn mal gar nichts mehr geht, und der Befehl **reboot** vor einer gefühlten Stunde immer noch nichts ausser Broadcast message from root@insider (pts/1) (Fri Oct 17 14:24:45 2014): The system is going down for reboot NOW! zustande gebracht hat gibt es quasi den Reset-Button für remote - den SysRq Key. Die Dokumentation beschreibt die Funktion so: ''It is a 'magical' key combo you can hit which the kernel will respond to regardless of whatever else it is doing, unless it is completely locked up.'' Dies erlaubt es eine hängende Maschine mehr oder weniger hart zu resetten. **Achtung:** Dabei gehen genauso wie beim Drücken der Reset Taste unter Umständen geliebte Daten verloren. Um z.B. eine hängende Maschine die den SysRq Trigger unterstützt (die Datei ///proc/sysrq-trigger// ist vorhanden): sync & sleep 5 echo b > /proc/sysrq-trigger === Links === * [[https://www.kernel.org/doc/Documentation/sysrq.txt|SysRq Dokumentation]] ===== Mastering your daemons ===== Daemonen nennt man in Unix-artigen Betriebssystemen alle Hintergrundprozesse. Meist werden diese Dienste bereits beim Systemstart abhängig vom aktuellen Runlevel gestartet, manche aber auch erst später bei Bedarf. In den meisten Serversystemen werden zurzeit noch System-V basierte Init-Skripte verwendet, der Umbruch zu systemd steht aber bevor und ist bei einigen Desktop Betriebssystemen bereits angekommen. Die Einführung von systemd wird von vielen Kontroversen begleitet, von den Gegnern wird kiritisiert, dass aufwändig ein Problem gelöst wird dass für den grössten Teil der Anwender nicht existiert und für den Rest nur minimale Verbesserungen bringt. Andererseits will man Linux auf dem Desktop dem Endanwender schmackhaft machen und dafür zählt unter anderem auch die Aufstartzeit dazu. Ubuntu wiederum verwendet Upstart und hat damit einen Mittelweg eingeschlagen. Wie man auf seinem spezifischen Linux Dienste administriert, einrichtet oder startet und beendet entnimmt man am Besten der Webseite der entsprechenden Distribution. Wir wollen hier nur kurz aufzeigen, welche Möglichkeiten man hat, um ein (selbstgeschriebenes) Programm beim Systemstart mitzustarten oder auch nur - nachdem man die Sitzung beendet hat - im Hintergrund weiterlaufen zu lassen. === Links === * [[https://wiki.debian.org/Daemon|Debian Daemons]] * [[http://upstart.ubuntu.com/cookbook/|Ubuntu Upstart]] * [[http://www.rpm-based.org/how-to-manage-services-with-chkconfig-and-service|Redhat based: chkconfig]] * {{:linux:debiankuerzel.pdf|Debian Referenzkarte}} ==== Programme im Hintergrund betreiben ==== === nohup === Nehmen wir folgendes Beispiel vom Anfang: /usr/local/bin/jobctl1.sh & Wenn wir nun die Shell beenden, beendet auch dieses Programm da ihm die Standardeingabe und Standardausgabe entzogen werden. Das kann mit dem **nohup** Tool umgangen werden: nohup /usr/local/bin/jobctl1.sh & Dieses Programm läuft nun auch nach dem Beenden der Shell oder Schliessen des Termninals im Hintergrund weiter. Etwaige Ausgaben werden dabei in die Datei //nohup.out// im aktuellen Verzeichnis geschrieben. === screen === Wenn man sich später wieder mit der Ausgabe des Programms verbinden will, ist **screen** die richtige Antwort dafür. Screen ist ein Terminal Multiplexer der auch im Hintergrund weiterläuft. Start einer neuen screen Session oder aufnehmen einer bestehenden falls eine besteht: screen -R Wichtige Tastenkombination in Screen: ^ Kombination ^ Funktion ^ | **CTRL+a d** | Detach der Session (kann mit screen -R wieder aufgenommen werden) | | **CTRL+a c** | Neues Fenster mit einer neuen Shell innerhalb der Sitzung anlegen | | **CTRL+a S** | Aktuelles Fenster splitten | | **CTRL+a X** | Aktuelles Splitfenster aufheben | | **CTRL+a n** | Ein Fenster weiter springen | | **CTRL+a p** | Ein Fenster zurück springen | ==== Dienst beim Systemstart starten ==== === Variante 1: rc.local === In fast allen Unix-artigen Systemen wird am Ende des Startvorgangs die Datei ''/etc/rc.local'' abgearbeitet. Im Normalfall ist eine leere Datei vorhanden wenn dies vom System unterstützt wird. Bei einem Debian basierten System sieht das so aus: #!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. exit 0 Eine oder mehrere entsprechende Kommandozeile sollte vor dem ''exit 0'' eingefügt werden. === Variante 2: cron === Der Scheduler Dienst ''cron'' läuft auf nahezu ausnahmslos jedem System. Im Gegensatz zu obigen Beispiel ist es auch möglich als ganz normaler User ohne root-Rechte eine Tabelle für cron - eine sogenannte crontab - zu erstellen. Um z.B. ein Skript bei jedem Start laufen zu lassen, erstellt man sich mit **crontab -e** einen crontab mit etwa einem solchen Eintrag: # m h dom mon dow user command @reboot echo "System Neustart um: $(date)" >> $HOME/reboot.log Das soll nur als Beispiel dienen und ist nicht wirklich von Nutzen. Dafür gibts ja auch den Befehl **uptime**. ===== Linux-Fu ===== Hier noch zur Unterhaltung einige wahllos zusammengestellte Trickchen, die den Appetit, sich mit dem einen oder anderen etwas mehr auseinanderzusetzen steigern soll: ==== FUSE - Filesystem in Userspace ==== Was etwas sperrig tönt, ist tatsächlich ein vielseitiges und hilfreichs Feature von BSD oder Linux Systemen. FUSE ermöglicht es dem Anwender ohne die nötigen Privilegien Dateisysteme zu mounten. Tönt dröge, aber schauen wir mal auf die verfügbaren FUSE Dateisysteme um eine Idee davon zu kriegen was man damit machen kann: * [[http://wiki.ubuntuusers.de/EncFS|EncFS]] - EncFS (Encrypted Filesystem) ist eine Verschlüsselungserweiterung für Unix-artige Dateisysteme * [[https://sr71.net/projects/gmailfs/|gmailfs]] - GMail Filesystem over FUSE * [[http://fuse.sourceforge.net/sshfs.html|sshfs]] - SSHFS ist ein FUSE-Modul, mit dem man entfernte Rechner über SSH in das eigene Dateisystem einbinden kann. * [[http://mysqlfs.sourceforge.net/|MySQLfs]] - ist ein FUSE-Modul zur Speicherung von Daten in MySQL Datenbanken * [[http://sourceforge.net/projects/httpfs/files/httpfs2/|httpfs]] - FUSE-Modul zum Einbinden von Dateien von HTTP-Servern * [[http://curlftpfs.sourceforge.net/|CurlFtpFS]] - FUSE-Modul zum Einbinden von FTP-Servern Die Möglichkeiten von FUSE sind schier unendlich, so können FUSE Module selbst sehr einfach in Perl, Python oder C erstellt werden. Anwendungen könnte z.B. ein embedded System sein, welches eine Datei automatisch sliced und dann druckt die im FUSE Dateisystem abgelegt wird. Oder Dokumente automatisch übersetzt oder faxt oder druckt etc... === FUSE Beispiele === Einbinden eines FTP Servers: curlftpfs ftp://mirror.switch.ch/ ~/mnt/ Einbinden einer Datei von einem HTTP Server: httpfs2 http://downloads.arduino.cc/arduino-1.0.6-linux32.tgz ~/mnt Einbinden eines Dateisystems oder Teil davon via sshfs: sshfs user1@host.tld:/home/user1/ ~/mnt/ Unmounten mit: fusermount -u ~/mnt === Links === * [[http://fuse.sourceforge.net/|FUSE Home]] * [[wpde>Filesystem_in_Userspace|Wikiepedia: FUSE (de)]] ==== Netcat - Schweizer Armee Messer für IP Netzwerke ==== Netcat ist ein äusserst hilfreiches Werkzeug für die Störungssuche im Netzwerk. Es kann aber auch für einfachere Netzwerkdienste eingesetzt werden. Eine Datei von einem Webserver abrufen: echo -e "GET /index.html HTTP/1.1\nHost: www.boxtec.ch\n\n"|nc www.boxtec.ch 80 Eine Diskpartition übers Netzwerk clonen: dd if=/dev/hda1 | gzip -9 |nc target.host.com 8000 Ausgabe des Netzwerkduchsatz auf TCP Port 8001: while [ 1 ]; do nc -l -p 8001 -e /usr/local/bin/netload.sh; done === Links === * [[http://www.computerhope.com/unix/nc.htm|Linux and Unix nc command]] * [[https://www.digitalocean.com/community/tutorials/how-to-use-netcat-to-establish-and-test-tcp-and-udp-connections-on-a-vps|How To Use Netcat to Establish and Test TCP and UDP Connections]]