# Einführung in Linux
YALC - Yet Another Linux Course
Author: Daniel Schubert

# LINUX

### Das universelle Betriebssystem

Eine Einführung - Teil 4

Deutsche Angestellten Akademie

## Bash Scripting

### Einführung und Übung

Erste skripte, Übungen

### Bash Scripting - Warum sollte ich das tun??

- Automatisierung
- Vereinfacht komplizierte Vorgänge
- Verringert den Fehlerfaktor „Mensch“
- YOLO !!1!

### Grundlegende Mechanismen

Begriffe

Wurzelverzeichnis / (engl. root) | Höchstes Verzeichnis im Verzeichnisbaum
Aktuelles Arbeitsverzeichnis | Das Verzeichnis, in dem Sie sich im Augenblick befinden
Vollständige Pfadangabe | Ein Pfadname beginnend mit / (Wurzel); alle anderen Verzeichnisse werden ebenfalls mit einem / getrennt.
Relative Pfadangabe | Der Pfad ist relativ zum aktuellen Arbeitsverzeichnis; hierbei wird kein voranstehendes / verwendet.
Vollständiger Dateiname | Pfadangabe inklusive Angabe zur entsprechenden Datei (bspw. /home/you/Dokumente/brief.txt)
Vollständiger Pfadname | Pfadangabe zu einem Verzeichnis, in dem sich die entsprechende Datei befindet (bspw. /home/you/Dokumente)
.. (zwei Punkte) | Verweisen auf ein Inhaltsverzeichnis, das sich eine Ebene höher befindet
. (ein Punkt) | Verweist auf das aktuelle Inhaltsverzeichnis

Benennung von scripten

- (lieber) kein Name, den es bereits als Kommando gibt. Einfach testen mit

      which script_name

- Nur die Zeichen {A..Z}, {a..z}, {0..9} und _ . Sonderzeichen und [space] vermeiden.

### Sonderzeichen in der Shell

    ;                       Befehls-Trennzeichen
    &                       Hintergrund-Verarbeitung
    ( )                     Befehls-Gruppierung
    |                       Pipe
    < > &                   Umlenkungssymbole
    * ? [ ] ~ + - @ !       Meta-Zeichen für Dateinamen
    ` ` (Backticks)         Befehls-Substitution
    $                       Variablen-Substitution
    [newline] [space] [tab] Wort-Trennzeichen

### Variablen

     a=hello     # einer Variablen "a" den Wert "hello" zuweisen
     echo $a     # die Variable "a" stdout ausgeben
     a=7         # der Variablen "a" einen neuen Wert zuweisen
     b=8         # einer Variablen "b" den Wert "8" zuweisen
     c=$[a+b]    # einer Variablen "c" die Summe von a+b zuweisen
     echo $c     # die Variable "c" an stdout ausgeben

### vordefinierte Variablen ( Auszug ;-) )

    *     Alle Aufrufparameter als ein String ("$*" == "$1 $2 $3 ...")
    @     Alle Aufrufparameter als einzelne Strings ("$@" == "$1" "$2" "$3" ...)
    #     Anzahl der Aufrufparameter
    ?     Rückgabewert des letzten Kommandos
    $     Prozessnummer der aktiven Shell
    0     Name des aktuellen script
    ERRNO    Fehlernummer des letzten fehlgeschlagenen Systemaufrufs
    PWD      Aktuelles Verzeichnis (wird durch cd gesetzt)
    PATH     Suchpfade
    USER     Benutzername

Beispiele

    echo $PATH

    echo $$

Mehr: http://wiki.bash-hackers.org/syntax/shellvars

Var. Zuweisung:

    a=10

Var. Abruf:

    echo $a

Programmstart

- Programm startet durch Aufruf :

      ls

- überall im Verz. Baum
- Script muss executable gemacht werden

      chmod +x tolles_script.sh

- Script startet durch Aufruf

      ./tolles-script.sh

Damit ein Script wie ein Programm startet:

- Pfad d. Skriptes der $PATH Variable hinzufügen

-     export PATH=$PATH:/pfad/zum/script

- muss in die .bashrc
- Best Practice: Scripte in Ordner `~/bin/` -> diesen zur `$PATH` dazu

PATH nur in der aktuellen Sizung -> sonst in die .bashrc

## Gentlemen, open your Editor!

    #!/bin/bash
    clear
    echo "Diese Infos werden von mysystem.sh bereitgestellt."
    echo "Hallo, $USER"

    echo "Heute ist der `date \"+%d.%m.%Y - %H:%M:%S\"`, dies ist Woche Nr. `date +"%V"`."
    echo

    echo "Diese Benutzer sind im Moment verbunden:"
    w | cut -d " " -f 1 - | grep -v USER | sort -u
    echo

    echo "Dies ist `uname -s` und wir laufen auf einem $(uname -m) Prozessor."
    echo

    echo "Die uptime ist:"
    uptime

    MSG="\nDas ist alles! Bye, $USER! \n\n"
    printf "${MSG}"

https://www.schubertdaniel.de/linuxkurs

https://git.scytec.de/danthefan/linuxkurs/raw/master/beispiele/mysystem.sh

    echo "Hallo, $USER"

    echo "Heute ist der `date \"+%d.%m.%Y - %H:%M:%S\"` "

    w | cut -d " " -f 1 - | grep -v USER | sort -u

    `uname -s`  vs  $(uname -s)

    MSG="\nDas ist alles! Bye, $USER! \n\n"
    printf "${MSG}"

Ausführende Shell festlegen ( sog. She-Bang )

    #!/bin/bash

    #!/usr/bin/env ruby

    #!/usr/bin/env python3

    #!/usr/bin/php

Nötig, damit die shell weiss, wie das script interpretiert werden soll.
Script ohne she-bang:

    bash mysql-backpup.sh

    . mysql-backpup.sh

oder

    php mysql-backpup.php

oder

    ruby mysql-backpup.rb

Prozess in der bash - Erklärung:

neue Datei anlegen : finduser

    #!/bin/bash
    find / -user dany -print 2>/dev/null

Dann im Terminal ausführen

    dany@laptop:~/bin$ chmod u+x finduser
    dany@laptop:~/bin$ ./finduser 1>/dev/null &

    dany@laptop:~/bin$ ps -f

    UID        PID  PPID  C STIME TTY          TIME CMD
    dany      4987 23893  0 12:50 pts/4    00:00:00 /bin/bash ./finduser
    dany      4988  4987 68 12:50 pts/4    00:00:01 find / -user dany -print
    dany      5011 23893  0 12:50 pts/4    00:00:00 ps -f
    dany     23893  4143  0 12:33 pts/4    00:00:00 bash

Die bash startet eine sub-shell, in der das Kommando ausgeführt wird

Der Kontext aller Script Variablen ist der der sub-shell

Aufgabe: Erstellt ein script, das alle Dateien in eurem home in einer tar.gz - Datei archiviert, das Verzeichnis "~/archiv" erstellt, und die tar.gz Datei dorthin verschiebt.
Hinweis: tar -czf .....

https://linuxconfig.org/bash-scripting-tutorial

    #!/bin/bash
    tar -czf myhome_directory.tar.gz /home/$USER
    mkdir archiv
    mv myhome_directory.tar.gz archiv/

### Kontrollstrukturen

#### if then

    #!/bin/bash
    cd
    ls
    if [ -e sample.sh ]
    then
     echo "file exists!"
    else
     echo "file does not exist"
    fi

#### if then elif

    #!/bin/bash
     cd
    ls -l
    read -p "Enter a file name: " filename
    if [ -e $filename ]
    then
     echo "file exists!"
     if [ -r $filename ]
     then
          status="readable "
     fi
     if [ -w $filename ]
     then
          status=$status"writable "
     fi
     if [ -x $filename ]
     then
          status=$status"executable"
     fi
      echo "file permission: "$status
    else
     echo "file does not exist"
    fi

#### for loop

    #!/bin/bash
    for f in {1..9}
    do
    	touch "$f xx.txt"
    done

Ein weiteres Beispiel:

    #!/bin/bash
    suf=$1
    if [ $# -gt 0 ]
      then
        for file in *.$suf; do
          bn=`basename "$file" .$suf | tr [:blank:]  _`
          new=$bn.$suf
          echo "neuer Dateiname:"
          echo $new
          mv "$file" $new
        done
      else
        echo "Verwendung: strip-space.sh SUFFIX"
        echo "Beende ...."
    fi

beispiele/create_files_with_spaces.sh

#### case

    #!/bin/bash
     clear
     read -p "Integer1: " int1
     read -p "Integer2: " int2
     printf "Menu: \n[a] Addition\n[b]Subtraction\n[c]Multiplication\n[d]Division\n"
     echo "======================"
     read -p "Your choice: " choice
     res=0
     case $choice in
    	 a)
    	     res=$((int1+int2))
    	 ;;
    	 b)
    	     res=$((int1-int2))
    	 ;;
    	 c)
    	     res=$((int1*int2))
    	 ;;
    	 d)
    	     res=$((int1/int2))
    	 ;;
    	 *)
    	     echo "Invalid input"
     esac
     echo "The result is: " $res

#### while loop

    #!/bin/bash
    x=1
    while [ $x -le 5 ]
    do
      echo "Welcome $x times"
      x=$(( $x + 1 ))
    done

#### until loop

    #!/bin/bash
    i=1
    until [ $i -gt 6 ]
    do
    	echo "Welcome $i times."
    	i=$(( i+1 ))
    done

### while vs until

1. until läuft bis Bedingung nicht 0 (false)
2. while läuft bis Bedingung 0 (true)
3. until läuft mind. einmal