===== La shell di Unix ===== La shell e’ l’interfaccia testuale tramite la quale l’utente interagisce con il sistema dopo il login. * E’ un interprete di comandi: legge ciascuna linea di comando, la interpreta e la esegue. * Non ha bisogno di particolari privilegi durante l’esecuzione. L’eventuale interazione con l’hardware avviene tramite system calls. * Ogni sistema Unix mette a disposizione vari tipi di shell. Le piu’ diffuse sono: Bourne shell (sh) , C shell (csh), TC shell (tcsh) e Bourne Again shell (bash). * Inizialmente l’amministratore del sistema fornisce ad ogni utente una shell di default che pero’ puo’ essere cambiata (chsh) * Ogni shell fornisce un linguaggio di programmazione. I programmi di shell sono denominati “shell script”. * D’ora in avanti faremo riferimento alla shell bash ==== Riferimenti e approfondimenti ==== [[ http://www.autistici.org/hacklab_fi/risorse/DM/MyLinuxch4.html#x223-910003| Informatica e GNU/Linux: La shell e i Job]] [[http://www.pluto.it/ildp/guide.html | Guide ILDP]] [[http://tldp.org/LDP/abs/html/ | Advanced Bash-Scripting Guide ]] ==== Comandi ==== * I comandi che la shell riconosce possono essere interni alla shell stessa (built-in) oppure file eseguibili esterni . * A pari nome i comandi interni hanno la precedenza * La sintassi tipica di un comando e’: comando * Argomenti: Si possono avere nessuno, uno o piu’ argomenti. Alcuni argomenti sono opzionali. Se non specificati assumono un valore di default. ( es: ls oppure ls /etc ) * Opzioni: sono opzionali ed influenzano il comportamento del comando. Generalmente consistono di un - seguiti da una lettera (es: ls -a ) Per alcune opzioni esiste anche la forma estesa (es: ls --all) Alcune opzioni possono avere un argomento (es: ls -T 2 ) == Esempi == date # visualizza la data corrente who # visualizza l’elenco degli utenti interattivi connessi al sistema whoami uname -a # mosta informazioni sul sistema ps # visualizza i processi attivi dell’utente ps -ef # visualizza tutti i processi quota ==== Editing della linea di comando ==== Ctrl-a : va ad inizio riga Ctrl-e : va a fine riga Ctrl-k : cancella il resto della riga Ctrl-y : reinserisce la stringa cancellata Ctrl-d : cancella il carattere sul cursore La shell registra i comandi inseriti dall’utente. history : elenca i comandi digitati in precedenza !n : richiama l’ennesimo comando dell’history !! : richama il comando precedente ↑↓ : naviga nella history Tab : completa il comando o il nome del file parzialmente digitato ==== Alias ==== Il comando alias permette di definire un alias. Ad esempio: alias #Il comando alias senza argomenti mostra tutti gli alias definiti. alias dir='ls -CF' alias rm='rm -i' ==== Variabili ==== Una variable e’ definita quando contiene un valore, compresa la stringa nulla. Per definire una variabile: nome_var=valore Per utilizzarne il contenuto: $nome_var (notare il $ in testa) Esempio: miofile=/home/didattica/xxxxxx/miofile.txt cat $miofile Il comando set visualizza l’elenco delle variabili definite (oltre alle eventuali funzioni di shell) == Variabili d'ambiente == Normalmente le variabili hanno validita’ limitata nell’ambito della shell stessa. Per esportare le variabili e i loro valori anche ai processi generati dalla shell e’ necessario utilizzare il comando export. Una variabile esportata e' detta variabile d'ambiente. Esempio: password=/etc/passwd export oppure export password=/etc/passwd Provare: test1="solo una prova" # con e senza export echo $test1 bash echo $test1 Per elencare le variabili d'ambiente: printenv == Variabili della Bash == Le variabili d'ambiente vengono utilizzate da diversi programmi e tools per gestire la modalita' di funzionamento. La Shell stessa utilizza diverse variabili d'ambiente. Le principali sono: PATH Elenco di directory in cui vengono cercati gli eseguibili. TERM Denota il tipo di terminale usato per le sessioni interattive LANG stabilisce il quale lingua mostare i messaggi. BASH_ENV Inizializzazione shell non interattiva UID Numero dell’UID dell’utente HOME La directory Home dell’utente PWD La directory di lavoro dell’utente PS1 Prompt ==== Inizializzazione==== La shell puo' essere eseguita in diverse modalita': * interattiva : standard input output ed error sono associate ad un terminale * login : shell interattiva invocata al momento del login ==Al momento dell'attivazione vengono eseguiti diversi script di inizializzazione a seconda del tipo di shell== ==Login== 1) /etc/profile + /etc/profile.d/*.sh 2) ~/.bash_profile | ~./bash_login | ~/.profile (il primo che viene trovato) == Non Login == * Interactive: ~/.bashrc * non-interactive: $BASH_ENV (default ~/.bashrc) La shell di login viene lanciata dopo la procedura di accesso e ha generalmente il nome di –bash (echo $0). Le shell successive (interattive e non) avranno il nome bash (senza trattino) Vedi [[ https://github.com/sstephenson/rbenv/wiki/Unix-shell-initialization | qui ]] le principali modalita' di apertura di una shell. ==== Gestione del file ==== Dal punto di vista utente tutti i files di un calcolatore sono organizzati all’interno di un unico file-system virtuale (VFS). Un nome nel file-system puo’ riferirsi a: * File-dati (es: /bin/ls) * Dispositivo di input/output (es: /dev/cd0) * Informazioni sul sistema (es: /proc/cpuinfo) * Memoria interna Per tradizione esistono alcune directory che hanno un ruolo particolare: / E' la radice della gerarchia /bin Comandi per l’utente /sbin Comandi di amministrazione /dev Dispositivi di I/O /dev/shm File in memoria RAM /etc File di configurazione del sistema /lib Librerie /var File di dimensione variabile (es: logs, mailbox) /usr File non essenziali ma utili /home Directory personali degli utenti /proc Contiene informazioni dinamiche di sistema ==== Working Directory ==== In Unix ogni processo ha associato una directory di lavoro (Working Directory) che puo’ essere visualizzata ( pwd ) e modificata dinamicamente ( cd newdir ). La directory di lavoro serve per evitare di doversi riferire ai file e alle directory del file-system in modo assoluto, ovvero specificando l’intero percorso a partire dalla radice (\). Se utilizziamo la Working dir. possiamo utilizzare riferimenti relativi alla directory di lavoro. Esempi: cd /home/ ls user1/ ==== Le directory . e .. ==== Ogni directory contiene 2 directory speciali: .. E’ un riferimento relativo alla directory genitore . E’ un riferimento relativo alla directory stessa Esempi: cd /home/user1 ls ../user2 cd ../user2 ./prog1 ==== home directory ==== In Unix ad ogni utente viene assegnata una Home Directory che e’ la parte del file-system destinata a contenere i file personali dell’utente. Il nome della home directory solitamente coincide con lo username dell'utente (ad esempio user1 ). Questa directory non e’ modificabile dall’utente ed è riferita come: ~user1/ Se lo username non e’ specificato si intende lo username dell’utente che ha generato il comando. I seguenti comandi, lanciati dall’utente user1, sono equivalenti: cd ~/bin cd ~user1/bin cd /home/user1/bin Il comando cd senza argomenti cambia la Working directory sulla Home dir. ==== comando ls ==== Il comando ls permette di visualizzare il contenuto di una o piu’ directory. Principali opzioni: -a visualizza anche i file nascosti (che cominciano con . ) -l visualizza informazione estesa sui file -F aggiunge un carattere finale al nome che ne denota il tipo: /->dir *->exe @->link =->socket nessuno-> file_ordinario -R visualizza ricorsivamente le sottodirectory Esempi: ls -R ~ #mostra ricorsivamente tutte le dir dell’utente. ==== comandi cp, mv, rm, mkdir e rmdir ==== cp copia un file cp oldfile newfile Per copiare ricorsivamente una dir preservando proprietario e permessi: cp -Rdp olddir/ newdir/ mv sposta un file (come cp, ma l’originale e’ cancellato) rm cancella un file rm oldfile mkdir crea una nuova directory mkdir newdir rmdir cancella una directory esistente rmdir olddir La directory da cancellare deve essere vuota. Per cancellare una directory e, ricorsivamente, tutto il suo contenuto (fare attenzione!!) : rm -r olddir/ ==== gli attributi dei file e il comando chown ==== Ad ogni file e’ associata una lista di attributi, tra cui: * Identificativo del proprietario * Identificativo del gruppo * Permessi di accesso * Data di creazione *(ls –l)* * Data di ultimo accesso (ls –lu) * Data di ultima modifica (ls –lc) L’identificativo del proprietario e del gruppo possono essere modificati con il comando chown. Esempi: chown user1 file1 cambia proprietario chown user1:group1 file1 cambia proprietario e gruppo ==== Permessi di accesso ai File ==== I permessi di accesso possono essere: r(lettura) w(scrittura) x(esecuzione) -(mancanza di permesso) Esempio: -rw------- 1 user1 group1 1234 Jan 1 10:00 dati1 -rwxr-x--- 1 user1 group1 1234 Jan 1 10:00 prog1 xrwxr-xr-x 2 user1 group1 1234 Jan 1 10:00 dir1 Per accedere al contenuto di una directory e’ necessario il permesso “x” Per accedere ad un file e’ quindi necessario, oltre al permesso sul file, anche il permesso “x” per tutte le directory attraversate. ==== I comandi chmod e umask ==== Il comando chmod consente di modificare i permessi di accesso. Esiste una sintassi letterale e una numerica. Con la sintassi numerica ogni tripletta e’ codificata in ottale: --- 000 (0) --x 001 (1) -w- 010 (2) -wx 011 (3) r-- 100(4) r-x 101 (5) rw- 110 (6) rwx 111 (7) Esempio: chmod 644 file1 -> rw-r--r-- umask e’ utilizzato per assegnare i permessi di default ai nuovi file. Viene inserito tipicamente nei file di inizializzazione della shell La sintassi e’ ottale, ma diversamente da chmod gli 1 indicano rimozione del permesso rispetto al default di Unix che e’ 666 per i file e 777 per le directory. Per cui ad esempio: umask 002 sottrae i permessi wx alla terza tripletta (others) quindi i nuovi file avranno permessi 664 mentre le directory avranno 774 ==== Visualizzare i file con cat, less, head e tail ==== Il comando **cat** concatena e visualizza sullo schermo il contenuto di uno o piu’ file: cat file1 file2 I comandi **more** e **less**, mediante opportuni comandi a carattere, consentono il controllo dell’area visibile, consentendo lo spostamento verso l’inizio o la fine del file, e ricerche di stringhe I comandi **head** e **tail** consentono di visualizzare le 10 righe in testo o in coda al file. Una opzione interessante del comando tail e’ -f la quale mantiene aperto il file e quindi consente di visualizzare in tempo reale eventuali nuovi accodamenti al file. ==== Cercare informazioni sui file ==== Il comando whereis cerca la locazione di un programma tra i sorgenti, eseguibili e i manuali: whereis [-bms] which Il comando which cerca il path completo o l’alias di un comando. Il comando du (disk usage https://www.tecmint.com/check-linux-disk-usage-of-files-and-directories/ ) ritorna l'utilizzo di file e directory. Esempi: du -ha $HOME/html du -ca $HOME du -ca $HOME/ du -hd1 $HOME --exclude=tsclient/* | sort -n | tail ==== Archivi e compressione ==== Il comando **tar** consente di gestire archivi: tar -cf file_da_archiviare # crea tar -tf # mostra il contenuto tar -xf # estrare un archivio Esempio: tar –xf miobackup.tar restore/ Il comando **gzip/gunzip** permette di comprimere/decomprimere un file (utilizzando la codifica Lempel-Ziv). Esempi: gzip myfile # genera myfile.gz gunzip myfile.gz # ripristina myfile Il comando tar –czf crea un archivio e lo comprime con gzip (.tar.gz) Il comando tar –xzf estae un archivio compresso ==== Metacatatteri per il pattern matching ==== All’interno di nomi di file possiamo includere dei caratteri speciali permettono di riferirsi a diversi nomi di file con un’unica stringa: ? -> Qualunque singolo carattere al posto di ? * -> Qualunque stringa di caratteri al posto di * [set] -> Qualunque singolo carattere incluso nel set [!set] -> Qualunque singolo carattere tranne quelli inclusi nel set Se la Bash trova un nome di file contenente Metacaratteri lo espande con tutti i nomi che soddisfano (match) la sintassi. Esempi: ls c?t equivale a ls cat cbt cct cdt ecc. ls c*t elenca tutti i file che iniziano per c e finiscono per t. ls c[au]t equivale a ls cat cut ls c[!a-z]t elencai file di 3 carat. che iniziano per c e terminano per t escludendo le minuscole. c{ha,oa}t rappresenta le stringhe chat e coat ==== Descrittori di file per l'I/O ==== Ogni processo possiede un certo numero di file aperti con cui puo’ scambiare (leggere o scrivere ) dati. Ad ogni file aperto corrisponde un descrittore che e’ identificato da un numero. Esistono sempre almeno tre descrittori per ogni processo: * 0 = standard input; * 1 = standard output; * 2 = standard error. Per i processi interattivi (shell) lo standard input e’ associato alla tastiera, mentre output e error sono associati al video. Le shell supportano la possibilita’ di redirigere questi canali di I/O verso file. ==== Metacaratteri per la redirezione dell'I/O ==== cmd [n]> filename Redirezione dell’output (new file) (default n=1) cmd [n]>> filename Redirezione dell’output (append) (default n=1) cmd [n]< filename Redirezione dell’Input (default n=0) cmd [n]<&m Unione del descrittore n ad m (default n=0) cmd [n]>&m Unione del descrittore n ad m (default n=1) cmd1 << end Redirezione dell’input dalla linea di comando (here document) Esempi: wc << end uno due tre end wc << fine > miofile prova fine cat miofile1 miofile2 >a 2>b cat miofile1 miofile2 >a 2>&1 (stderr unito a stdout, ovvero al file a) Se miofile1 esiste e miofile2 non esiste, nel primo caso miofile1 viene ricopiato in a mentre in b va il messaggio di errore, nel secondo caso viene tutto scritto in a ====Metacaratteri per la gestione dei processi ==== cmd1 ; cmd2 Esecuzione in cascata di 2 comandi cmd1 & cmd2 Esecuzione concorrente di 2 comandi cmd1 | cmd2 Esecuzione in “pipe” di 2 comandi (l’output del primo e’ input per il secondo) cmd1 && cmd2 Il secondo comando e’ eseguito solo se il primo termina con successo (codice di ritorno uguale a 0) cmd1 || cmd2 Il secondo comando e’ eseguito solo se il primo ha un codice di ritorno non nullo ==== Altri metacaratteri === # Introduce un commento () Raggruppamento di comandi \ Il comando continua nella riga successiva Esempi: (cat a b 2> /dev/null && (echo file presenti > tmp) ) || \ (echo manca un file > tmp) ==== Quoting ==== Il meccanismo di quoting e’ utilizzato per inibire l’effetto dei metacaratteri. Ci sono 3 tipi di quoting: * Meccanismo con Escape (\) il quale inibisce l’effetto del metacarattere seguente. cp file file\? * Tutti i metacaratteri presenti in una stringa tra singoli apici perdono l’effetto speciale. cat file 'file*' * I metacaratteri per l’abbreviazione del pathname in una stringa tra doppi apici perdono l’effetto speciale. cat file "file*" ====I processi e la memoria virtuale==== Ogni processo ha un PID (Process ID) Ogni processo puo’ generare nuovi processi detti figli La radice della gerarchia di processi e’ il processo init con PID=1 ( vedi comando "pstree" ) Il comando ps fornisce i processi presenti nel sistema. Per elencare tutti i processi ps –el ps -el F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 100 S 0 1 0 0 68 0 - 328 do_sel ? 00:01:05 init 040 S 0 2 1 0 69 0 - 0 contex ? 00:00:00 keventd S=stato (T=stopped, S=Sleeping, R=running) PRI=Priority SZ=mem. virtuale (text+data+stack) WCHAN=evento su cui il processo e’ sleeping ==== Background dei processi ==== Ogni comando assegnato alla shell viene eseguito all’interno di un nuovo processo creato appositamente (a meno che non sia un comando interno). Esercizio: Spiegare la differenza dell’output tra ps & ps e ps ; ps Il processo della shell rimane sospeso fino alla terminazione dei processi che ha generato. Il processo figlio e’ detto in modalita’ Foreground e puo' essere terminato premendo ctrl/C. Esercizio: Provare xterm e quindi ctrl/C Se il comando ( sequenza di comandi) e’ terminato dal carattere & il processo generato e’ eseguito nella modalita’ Background. In questa modalita’ il processo genitore non rimane sospeso, ma continua la propria esecuzione in parallelo al figlio. Esercizio: xterm& L’esecuzione di un processo Foreground puo’ essere terminata (ctrl/C) o sospesa (ctrl/Z). Un processo sospeso puo’ tornare in Foreground con il comando fg oppure puo’ passare in Background con il comando bg. Il comando "jobs" mostra l’elenco dei processi in Background o sospesi. Esempi: xterm (ctrl/z) xclock& xeyes& jobs kill %1 fg %3 ==== Priorita' con nice e renice ==== Il sistema operativo gestisce i processi attivi mediante un meccanismo dinamico di priorità: ogni processo possiede una priorità di Base che viene modificata runtime dal sistema oparativo in funzione dello stato del processo. La priorità può essere aggiustata da nice nel campo di variazione tra -20 (la più alta priorità) a +19 (la più bassa). L'utente (non amministratore) puo' solo diminuire la priorita' dei propri processi (aumentando il nice). ==Esercizio== (xterm&) ; (nice xterm&) ; (nice -n 19 xterm&); ps -el L'utente puo' modificare il nice di un proprio processo in esecuzione con il comando renice. Esempio: renice 19 10618 (10618 e' il pid) ==== Temporizzare i comandi con crontab ==== Con crontab possiamo stabilire l'esecuzione periodica di un comando. Per listare tutte le temporizzazioni impostate sull'host: crontab -l # mostra il crontab impostato Formato (vedi man 5 crontab per la sintassi del file di configurazione): Minuto Ora Giorno-mese Mese Giorno-Settimana comando Esempio: 00 01 * * 1 "/bin/ls /etc > /tmp/ls.txt" #esegui il comando "/bin/ls /etc > /tmp/ls.txt" tutti i lunedi alle ore 01:00 Per editare la lista dei crontab si usa il comando export EDITOR=nano crontab -e