![it-logo-100x100.png](https://hackmd.io/_uploads/HkjdnyFXp.png)
### Εισαγωγή στο Bash
---
#### Τί είναι το Bash
Bash (**B**ourne-**A**gain **Sh**ell) ονομάζουμε:
- ένα συγκεκριμένο command line interface (CLI) και
- την scripting γλώσσα
Το Bash είναι το προεγκατεστημένο (default) κέλυφος (shell) σε πολλές διανομές Linux (Ubuntu, Debian, Fedora κ.α.) και ως εκ τούτου το χρησιμοποιούμε συχνά ως διαχειριστές τέτοιων συστημάτων.
---
#### Μερικά παραδείγματα CLIs
- Bourne shells: `sh`, `ash`, `zsh`, `ksh`, `bash`
- C shells: `csh`, `tcsh`
- Microsoft shells: `cmd.exe`, Windows PowerShell (`pwsh`)
---
#### CLI vs GUI
Σε αντίθεση με γραφικές διεπαφές (graphical user interfaces ή GUIs) όπου ο χρήστης έχει οπτικά πρόσβαση στις διάφορες επιλογές (κουμπιά) σε ένα CLI χρειάζεται να μάθουμε εκ των προτέρων κάποιες εντολές (λέξεις) που θα χρησιμοποιούμε.
Λίγες νέες "λέξεις" όμως είναι αρκετές συνήθως για να αυτοματοποιήσουμε και να τυποποιήσουμε επαναληπτικές διαδικασίες (κάτι που σε ένα γραφικό περιβάλλον χρήσης είναι αδύνατο να γίνει). Σημαντικό εργαλείο για την τυποποίηση διαδικασιών αποτελεί το pipelining (`|`) δηλαδή η ανακατεύθυνση της εξόδου μιάς εντολής ως είσοδο σε μιά ακόλουθη εντολή.
---
#### Ας ξεκινήσουμε...
Ο χαρακτήρας `$` συμβολίζει συνήθως το prompt.
```
$
```
Πιο συχνά το κέλυφος που βλέπουμε έχει την ακόλουθη μορφή:
```
[username@hostname path]$
```
Συνήθως, όταν έχουμε αυξημένα δικαιώματα το prompt υποδηλώνεται με το χαρακτήρα `#`, π.χ:
```
[root@hostname path]#
```
---
:::warning
:warning: Ποτέ δεν τρέχουμε κάτι ως χρήστης `root` εκτός και αν "ξέρουμε τι κάνουμε". Εφόσον "ξέρουμε τι κάνουμε", όταν κάποια στιγμή τρέξουμε κάτι ως χρήστης `root` και αυτό έχει ανεπιθύμητες ενέργειες (που δεν είχαμε υπολογίσει) φροντίζουμε πρώτα να ενημερώσουμε τι συνέβη και μετά να λύσουμε το πρόβλημα.
:::
---
#### Μερικές εντολές
```
$ ls
Desktop Downloads Movies Pictures
Documents Library Music Public
```
---
#### Συντακτικό λάθος
:::warning
:warning: Command not found
```
$ ks
-bash: ks: command not found
```
:::
---
#### Αρχεία ασκήσεων
Θα χρειαστεί να κατεβάσουμε το [zip αρχείο με τις ασκήσεις](https://packages02.it.auth.gr/repository/raw/ciops/onboarding/shell-lesson-data.zip) μέσα στο φάκελο Desktop και να το κάνουμε unzip. Αυτό μπορούμε να το κάνουμε είτε από το γραφικό περιβάλλον (αν έχουμε) είτε μέσω γραμμής εντολών εκτελώντας τις παρακάτω:
```
$ cd Desktop
$ wget https://packages02.it.auth.gr/repository/raw/ciops/onboarding/shell-lesson-data.zip
$ unzip shell-lesson-data.zip
```
:::info
:information_source: Οι τελευταίες δύο εντολές μπορεί να μη λειτουργήσουν καθώς προϋποθέτουν ότι στο σύστημα που εργαζόμαστε υπάρχουν εγκατεστημένα τα εργαλεία `wget` και `unzip`. Εφόσον δεν υπάρχουν μπορούμε να τα εγκαταστήσουμε με τον package manager του λειτουργικού συστήματος.
:::
---
#### Μερικές εντολές
```
$ cd shell-lesson-data
$ ls
$ ls -F
$ ls -F -a
$ ls -Fa
$ pwd
$ cd ../
$ pwd
$ echo hello world
$ ls -lrta
$ history
```
---
#### Επεξήγηση εντολών
- https://explainshell.com/
:::danger
:radioactive_sign: ΠΡΟΣΟΧΗ: μην εκτελέσετε ποτέ το πρώτο παράδειγμα της λίστας σε υπολογιστή σας ή remote linux server διότι είναι fork bomb
:::
- https://tldr.sh/
---
#### Σημαντικά σημεία για το σύστημα αρχείων
- Το σύστημα αρχείων έχει ρίζα στο `/`
- Υπάρχουν 2 βασικά είδη δεδομένων, τα αρχεία (files) και οι φάκελοι (directories ή folders)
- Τα ονόματα των φακέλων σε ένα path διαχωρίζονται με `/` σε Unix και με `\` σε Windows
- Με την `cd` μεταβαίνουμε σε (αλλάζουμε) φάκελο
- Η εντολή `pwd` τυπώνει το "πού" βρισκόμαστε στο σύστημα αρχείων
- Με την `ls` βλέπουμε τα περιεχόμενα ενός φακέλου (αρχεία και υποφακέλους)
- Οι εντολές παίρνουν παραμέτρους που εκκινούν με `-`
- Το αρχείο `.` είναι ο "εδώ" φάκελος, το αρχείο `..` ο "πιο πάνω" φάκελος
- Για να πάμε "πιο πάνω" στο σύστημα αρχείων μπορούμε να χρησιμοποιήσουμε το `cd ..`
---
#### Absolute vs relative paths
Έστω ότι o χρήστης `anna` με home στο `/home/anna` βρίσκεται στο path `/home/anna/Downloads/data`. Για να επιστρέψει στο `/home/anna` υπάρχουν οι εξής επιλογές
1. `cd ../../`
2. `cd ../..`
3. `cd`
4. `cd ~`
5. `cd /home/anna`
6. `cd ~/Downloads/..` κοκ...
---
#### Διαχείριση αρχείων
- `cp arg1 arg2` κάνει ένα αντίγραφο του αρχείου `arg1` με όνομα `arg2`
- `mv arg1 arg2` κάνει μετονομασία του αρχείου `arg1` σε `arg2`
- `mkdir arg1` φτιάχνει ένα νέο φάκελο με όνομα `arg1`
- `rm arg1` σβήνει το αρχείο `arg1`. Αν το `arg1` είναι φάκελος: `rm -r arg1`
- `find . -name data.txt` Θα αναζητήσει ένα αρχείο με όνομα `data.txt` από "εδώ και κάτω"
---
#### Wildcards
- ο χαρακτήρας `*` υποδηλώνει μηδέν ή περισσότερους (οποιουσδήποτε) χαρακτήρες
- `ls *.log`
- `find . -name "*.txt"`
- ο χαρακτήρας `?` υποδηλώνει έναν (και μόνο έναν) οποιονδήποτε χαρακτήρα
- `ls log-2023-10-0?.log`
---
#### Filtering data and pipelining (`grep` and `awk`)
```
$ cd semester_a
$ ls -lrta
$ file students.txt # show me the type of file
$ cat students.txt # show me the contents of the file
$ grep zzz students.txt # show me all lines that match the string zzz
$ wc -l students.txt # count me the lines
$ awk -F';' '{print $1}' students.txt # show me the 1st column
```
---
#### Redirection
```
$ cat schedule.txt
$ awk -F';' '{print $1,$2}' schedule.txt > monday_schedule.txt
$ ls -lrta
$ cat monday_schedule.txt
```
---
#### For loops
```
$ seq 2 7
$ for i in $(seq 1 6); do echo $i; done
$ for i in $(seq 2 6); do awk -F';' '{print $1,$'${i}'}' schedule.txt; done
```
---
#### Pipelining
```
$ for i in $(seq 2 6); do awk -F';' '{print $1,$'${i}'}' schedule.txt; done | grep zzz | wc -l
$ for i in $(seq 2 6); do awk -F';' '{print $1,$'${i}'}' schedule.txt; done | grep zzz | grep 12.00-13.00 | wc -l
```
---
#### Too much pipelining
Λάθος:
```
$ cat file.txt | grep string | awk '{print $NF}'
```
Σωστό:
```
$ grep string file.txt | awk '{print $NF}'
```
Πιο σωστό:
```
$ awk '/string/ {print $NF}' file.txt
```
---
#### Editing files (`nano`, `vim` etc)
- Το `nano` είναι καλή επιλογή για "αρχάριους"
:::info
:information_source: Εφόσον ανοίξουμε ένα αρχείο με `nano` μπορούμε να κάνουμε απευθείας edit και να κάνουμε αλλαγές. Στις 2 κάτω γραμμές στο παράθυρο του `nano` μας δίνονται ως επιλογές οι συνδυασμοί πλήκτρων για να σώσουμε τις αλλαγές μας (επιλογή `WriteOut` με <kbd>Crtl</kbd>+<kbd>O</kbd>) και να βγούμε από το περιβάλλον του editor (επιλογή `Exit` με <kbd>Crtl</kbd>+<kbd>X</kbd>)
:::
- Το `vim` έχει πιο απότομο learning curve
:::info
:information_source: To `vim` έχει δύο modes, το command mode και το insert (edit) mode. Όταν ανοίγουμε ένα αρχείο βρισκόμαστε σε command mode. Για να κάνουμε αλλαγές πρέπει να γυρίσουμε τον editor σε insert mode κάτι που γίνεται πατώντας <kbd>i</kbd> στο πληκτρολόγιό μας. Αφότου κάνουμε τις αλλαγές για να τις σώσουμε και να βγούμε από το περιβάλλον του editor πρέπει να επιστρέψουμε σε command mode, κάτι που γίνεται πατώντας το πλήκτρο <kbd>Esc</kbd> στο πληκτρολόγιό μας. Οι εντολές δίνονται επιλέγοντας "άνω κάτω" τελεία στο πληκτρολόγιο (<kbd>:</kbd>). Η εντολή για να σωθούν οι αλλαγές είναι `:w` και η εντολή για να βγούμε από τον editor είναι `:q`. Συνήθως τις δίνουμε μαζί ως `:wq` (προσοχή στη σειρά των εντολών, το `w` πρέπει να προηγείται του `q`).
:::
---
#### Χρήσιμοι συνδυασμοί για το τερματικό
| Συνδυασμός | Περιγραφή |
| --- | --- |
| Crtl+A | Μετακίνηση κέρσορα στην αρχή της γραμμής |
| Crtl+E | Μετακίνηση κέρσορα στο τέλος της γραμμής |
| Crtl+W | Σβήσιμο χαρακτήρων μέχρι το προηγούμενο κενό |
| Tab | Autocompletion |
| Πάνω/κάτω βέλος | Προηγούμενη/επόμενη εντολή από το ιστορικό εντολών |
| Crtl+R | Αναζήτηση στο ιστορικό εντολών |
| Crtl+C | Διακοπή εκτέλεσης |
---
#### Scripting
Στην πρώτη γραμμή δηλώνουμε το κέλυφος (interpreter) που θέλουμε να χρησιμοποιήσουμε, π.χ. για `bash` συνήθως χρησιμοποιούμε την εξής γραμμή:
```
#!/bin/bash
```
Η γραμμή αυτή ονομάζεται shebang. Άλλα παραδείγματα (άλλων interpreters) είναι π.χ:
- `#!/usr/bin/php8`
- `#!/usr/bin/env python3`
- `#!/usr/bin/perl`
---
#### Παράδειγμα με το schedule.txt
```bash=1
#!/bin/bash
export user=${1}
export current_hour=$(date +%H)
export current_day=$(date +%u)
export current_day=$(( $current_day + 1 ))
awk -F';' '{print $1,$'${current_day}'}' schedule.txt | grep ^${current_hour} | grep ${user}
```
---
#### Παράδειγμα αναζήτησης στο DuckDuckGo
```bash=1
#!/bin/bash
for i in "$@"; do
search_term+=${i}+
done
/usr/bin/firefox --new-window "https://duckduckgo.com/?q=${search_term}"
```
:::info
:information_source: Το παραπάνω για να δουλέψει προϋποθέτει ότι έχουμε εγκαταστήσει firefox browser στο λειτουργικό που εργαζόμαστε και ότι υπάρχει γραφικό περιβάλλον εργασίας ενεργοποιημένο.
:::
---
#### Linux server case challenges
- https://sadservers.com/