Una parte importante dell’imparare a lavorare con Ubuntu, e le distribuzioni Linux in generale, comporta l’acquisizione di competenza nel lavorare nell’ambiente shell. Mentre gli ambienti desktop grafici come GNOME inclusi in Linux forniscono un’interfaccia facile da usare per il sistema operativo, in pratica l’ambiente shell fornisce capacità, flessibilità e automazione molto più grandi di quelle che si possono ottenere usando strumenti desktop grafici. L’ambiente shell fornisce anche un mezzo per interagire con il sistema operativo quando un ambiente desktop non è disponibile; un evento comune quando si lavora con un sistema operativo basato su server come Ubuntu o un sistema danneggiato che non si avvia completamente.

L’obiettivo di questo capitolo, quindi, è quello di fornire una panoramica dell’ambiente shell di default su Ubuntu (in particolare la shell Bash).

1.1 Cos’è una Shell?

La shell è un ambiente interattivo interprete di comandi all’interno del quale i comandi possono essere digitati in un prompt o inseriti in un file sotto forma di script ed eseguiti. Le origini della shell possono essere fatte risalire ai primi giorni del sistema operativo UNIX. Infatti, nei primi giorni di Linux prima dell’introduzione dei desktop grafici la shell era l’unico modo per un utente di interagire con il sistema operativo.

Una varietà di ambienti shell sono stati sviluppati nel corso degli anni. La prima shell ampiamente utilizzata fu la Bourne shell, scritta da Stephen Bourne ai Bell Labs.

Un’altra prima creazione fu la C shell che condivideva alcune somiglianze di sintassi con il linguaggio di programmazione C e introdusse miglioramenti di usabilità come la modifica della riga di comando e la cronologia.

La shell Korn (sviluppata da David Korn ai Bell Labs) è basata su caratteristiche fornite sia dalla shell Bourne che dalla shell C.

La shell predefinita su Ubuntu è la shell Bash (abbreviazione di Bourne Again SHell). Questa shell, che ha iniziato la sua vita come una versione open source della shell Bourne, è stata sviluppata per il progetto GNU da Brian Fox e si basa su caratteristiche fornite sia dalla shell Bourne che dalla shell C.

1.2 Accedere alla Shell

Dall’interno dell’ambiente desktop GNOME, si può accedere al prompt della shell da una finestra del Terminale selezionando l’opzione Attività nella barra in alto, inserendo Terminale nella barra di ricerca e cliccando sull’icona del Terminale.

Quando si accede da remoto a un server Ubuntu, per esempio usando SSH, all’utente viene anche presentato un prompt della shell. I dettagli sull’accesso a un server remoto usando SSH saranno trattati nel capitolo intitolato “Configurare l’autenticazione basata su chiave SSH su Ubuntu”. Quando si avvia un sistema basato su server in cui non è stato installato un ambiente desktop, la shell viene inserita immediatamente dopo che l’utente ha completato la procedura di accesso al terminale della console fisica o alla sessione di accesso remoto.

1.3 Inserire i comandi nel prompt

I comandi vengono inseriti nel prompt dei comandi della shell semplicemente digitando il comando e premendo il tasto Invio. Mentre alcuni comandi eseguono compiti in silenzio, la maggior parte mostrerà una qualche forma di output prima di tornare al prompt. Per esempio, il comando ls può essere usato per visualizzare i file e le directory nella directory di lavoro corrente:

$ ls

Desktop Documenti Download Musica Immagini Modelli pubblici Video

I comandi disponibili sono integrati nella shell stessa, o risiedono nel file system fisico. La posizione sul file system di un comando può essere identificata usando il comando which. Per esempio, per scoprire dove risiede l’eseguibile ls sul file system:

$ which ls alias ls='ls --color=auto' /usr/bin/ls

E’ chiaro che il comando ls risiede nella directory /usr/bin. Notate anche che è configurato un alias, un argomento che sarà trattato più avanti in questo capitolo. Usando il comando which per localizzare il percorso di comandi che sono incorporati nella shell, si otterrà un messaggio che indica che l’eseguibile non può essere trovato. Per esempio, tentare di trovare la posizione del comando history (che è effettivamente incorporato nella shell piuttosto che esistere come eseguibile sul file system) risulterà in un output simile al seguente:

$ which history/usr/bin/which: no history in (/home/demo/.local/bin:/home/demo/bin:/usr/share/Modules/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin)

1.4 Ottenere informazioni su un comando

Molti dei comandi disponibili nella shell di Linux possono sembrare criptici all’inizio. Per trovare informazioni dettagliate su cosa fa un comando e come usarlo, usate il comando man specificando il nome del comando come argomento. Per esempio, per saperne di più sul comando pwd:

$ man pwd

Quando il comando di cui sopra viene eseguito, verrà visualizzata una descrizione dettagliata del comando pwd. Molti comandi forniranno anche informazioni aggiuntive se eseguiti con l’opzione -help a riga di comando:

$ wc --help

1.5 Bash Command-line Editing

I primi ambienti di shell non fornivano alcuna forma di capacità di editing delle linee. Questo significava che se si individuava un errore all’inizio di una lunga riga di comando che si stava digitando, si dovevano cancellare tutti i caratteri seguenti, correggere l’errore e poi reinserire il resto del comando. Fortunatamente Bash fornisce una vasta gamma di opzioni di modifica della riga di comando, come indicato nella tabella seguente:

Sequenza di tasti Azione
Ctrl-b o Freccia sinistra Sposta il cursore indietro di una posizione
Ctrl-f o Freccia destra Sposta il cursore in avanti di una posizione
Cancella Cancella il carattere attualmente sotto il cursore
Backspace Cancella il carattere a sinistra del cursore
Ctrl-_ Annulla la modifica precedente (può essere ripetuto per annullare tutte le modifiche precedenti)
Ctrl-a Sposta il cursore all’inizio della linea
Ctrl-e Sposta il cursore alla fine della linea
Meta-f o Esc poi f Spostamento del cursore in avanti di una parola
Meta-b o Esc poi b Spostamento del cursore indietro di una parola
Ctrl-l Cancella lo schermo da tutto tranne il comando corrente
Ctrl-k Cancella alla fine della linea dalla posizione corrente del cursore
Meta-d o Esc poi d Cancella alla fine della parola corrente
Meta-DEL o Esc poi DEL Cancella l’inizio della parola corrente
Ctrl-w Cancella dalla posizione corrente del cursore allo spazio bianco precedente

Tabella 9-1

1.6 Lavorare con la cronologia della shell

In aggiunta alle caratteristiche di modifica della riga di comando, la shell Bash fornisce anche il supporto alla cronologia della riga di comando. Un elenco di comandi precedentemente eseguiti può essere visualizzato usando il comando history:

$ history1ps2ls3ls –l /4ls5man pwd6man apropos

Inoltre, Ctrl-p (o freccia su) e Ctrl-n (o freccia giù) possono essere usati per scorrere avanti e indietro i comandi precedentemente inseriti. Quando viene visualizzato il comando desiderato dalla cronologia, premere il tasto Invio per eseguirlo.

Un’altra opzione è quella di inserire il carattere ‘!’ seguito dai primi caratteri del comando da ripetere seguito dal tasto Invio.

1.7 Stenografia per nomi di file

Molti comandi della shell prendono uno o più nomi di file come argomenti. Per esempio, per visualizzare il contenuto di un file di testo chiamato list.txt, il comando cat verrebbe usato come segue:

$ cat list.txt

Similmente, il contenuto di più file di testo potrebbe essere visualizzato specificando tutti i nomi dei file come argomenti:

$ cat list.txt list2.txt list3.txt list4.txt

Invece di digitare ogni nome, il pattern matching può essere usato per specificare tutti i file con nomi corrispondenti a certi criteri. Per esempio, il carattere jolly ‘*’ può essere usato per semplificare l’esempio precedente:

$ cat *.txt

Il comando precedente visualizzerà il contenuto di tutti i file che terminano con l’estensione .txt. Questo potrebbe essere ulteriormente ristretto a qualsiasi nome di file che inizi con list e finisca in .txt:

$ cat list*.txt

Corrispondenze di un singolo carattere possono essere specificate usando il carattere ‘?’:

$ cat list?.txt

1.8 Completamento di nomi di file e percorsi

Piuttosto che digitare un intero nome di file o percorso, o usare il pattern matching per ridurre la quantità di battitura, la shell fornisce la funzione di completamento dei nomi di file. Per usare il completamento del nome del file, inserite semplicemente i primi caratteri del nome del file o del percorso e poi premete due volte il tasto Esc. La shell completerà il nome del file per voi con il primo nome di file o di percorso nella directory che corrisponde ai caratteri che avete inserito. Per ottenere una lista di possibili corrispondenze, premete Esc = dopo aver inserito i primi caratteri.

1.9 Reindirizzamento di input e output

Come menzionato in precedenza, molti comandi della shell producono informazioni quando vengono eseguiti. Per default questo output va in un file di dispositivo chiamato stdout che è essenzialmente la finestra del terminale o la console in cui la shell è in esecuzione. Al contrario, la shell prende input da un file di dispositivo chiamato stdin, che per default è la tastiera.

L’output di un comando può essere reindirizzato da stdout a un file fisico sul file system usando il carattere ‘>’. Per esempio, per reindirizzare l’output di un comando ls a un file chiamato files.txt, sarebbe necessario il seguente comando:

$ ls *.txt > files.txt

Al completamento, files.txt conterrà la lista dei file nella directory corrente. Allo stesso modo, il contenuto di un file può essere inserito in un comando al posto di stdin. Per esempio, per reindirizzare il contenuto di un file come input a un comando:

$ wc –l < files.txt

Il comando precedente mostrerà il numero di linee contenute nel file files.txt.

È importante notare che l’operatore di reindirizzamento ‘>’ crea un nuovo file, o tronca un file esistente quando viene usato. Per aggiungere un file esistente, usate l’operatore ‘>>’:

$ ls *.dat >> files.txt

Oltre all’output standard, la shell fornisce anche un output di errore standard usando stderr. Mentre l’output di un comando è diretto a stdout, qualsiasi messaggio di errore generato dal comando è diretto a stderr. Questo significa che se stdout è diretto ad un file, i messaggi di errore appariranno comunque nel terminale. Questo è generalmente il comportamento desiderato, sebbene stderr possa anche essere reindirizzato, se desiderato, usando l’operatore ‘2>’:

$ ls dkjfnvkjdnf 2> errormsg

Al completamento del comando, un errore che riporta il fatto che il file chiamato dkjfnvkjdnf non può essere trovato sarà contenuto nel file errormsg.

Sia stderr che stdout possono essere reindirizzati allo stesso file usando l’operatore &>:

$ ls /etc dkjfnvkjdnf &amp;&gt; alloutput

Al completamento dell’esecuzione, il file alloutput conterrà sia un elenco del contenuto della directory /etc, sia il messaggio di errore associato al tentativo di elencare un file inesistente.

1.10 Lavorare con le pipe nella shell Bash

In aggiunta al reindirizzamento dell’I/O, la shell permette anche di convogliare l’output di un comando direttamente come input per un altro comando. Un’operazione di pipe si ottiene mettendo il carattere ‘|’ tra due o più comandi su una linea di comando. Per esempio, per contare il numero di processi in esecuzione su un sistema, l’output del comando ps può essere convogliato al comando wc:

$ ps –ef | wc –l

Non c’è limite al numero di operazioni di pipe che possono essere eseguite su una linea di comando. Per esempio, per trovare il numero di linee in un file che contengono il nome Smith:

$ cat namesfile | grep Smith | wc –l

1.11 Configurare gli alias

Quando si acquisisce familiarità con l’ambiente della shell è probabile che ci si trovi spesso a emettere comandi con gli stessi argomenti. Per esempio, potresti usare spesso il comando ls con le opzioni l e t:

$ ls –lt

Per ridurre la quantità di battitura necessaria per emettere un comando, è possibile creare un alias che corrisponde al comando e agli argomenti. Per esempio, per creare un alias in modo che inserendo la lettera l venga eseguito il comando ls -lt, verrebbe usata la seguente dichiarazione:

$ alias l="ls –lt"

Inserendo l al prompt dei comandi verrà eseguita la dichiarazione originale.

1.12 Variabili d’ambiente

Le variabili d’ambiente della shell forniscono una memorizzazione temporanea di dati e impostazioni di configurazione. La shell stessa imposta un certo numero di variabili d’ambiente che possono essere cambiate dall’utente per modificare il comportamento della shell. Un elenco delle variabili attualmente definite può essere ottenuto usando il comando env:

$ envSSH_CONNECTION=192.168.0.19 61231 192.168.0.28 22MODULES_RUN_QUARANTINE=LD_LIBRARY_PATHLANG=en_US.UTF-8HISTCONTROL=ignoredupsHOSTNAME=demo-pc.ebookfrenzy.comXDG_SESSION_ID=15MODULES_CMD=/usr/share/Modules/libexec/modulecmd.tclUSER=demoENV=/usr/share/Modules/init/profile.shSELINUX_ROLE_REQUESTED=PWD=/home/demoHOME=/home/demoSSH_CLIENT=192.168.0.19 61231 22SELINUX_LEVEL_REQUESTED= ...

La variabile d’ambiente forse più utile è PATH. Questa definisce le directory in cui la shell cercherà i comandi inseriti al prompt dei comandi, e l’ordine in cui lo farà. La variabile d’ambiente PATH per un account utente su un sistema Ubuntu appena installato sarà probabilmente configurata come segue:

$ echo $PATH/home/demo/.local/bin:/home/demo/bin:/usr/share/Modules/bin:/usr/local/bin:/usr/ bin:/usr/local/sbin:/usr/sbin

Un’altra variabile utile è HOME che specifica la directory home dell’utente corrente. Se, per esempio, volete che la shell cerchi anche i comandi nella directory degli script che si trova nella vostra home directory, modificherete la variabile PATH come segue:

$ export PATH=$PATH:$HOME/scripts

Il valore corrente di una variabile d’ambiente esistente può essere visualizzato usando il comando echo:

$ echo $PATH

E’ possibile creare le proprie variabili d’ambiente usando il comando export. Per esempio:

$ export DATAPATH=/data/files

Un utile trucco per assegnare l’output di un comando a una variabile d’ambiente comporta l’uso di virgolette (`) intorno al comando. Per esempio, per assegnare la data e l’ora attuali a una variabile d’ambiente chiamata NOW:

$ export NOW=`date`$ echo $NOWTue Apr 2 13:48:40 EDT 2020

Se ci sono impostazioni di variabili d’ambiente o alias che devono essere configurate ogni volta che si entra nell’ambiente della shell, possono essere aggiunte a un file nella propria directory home chiamato .bashrc. Per esempio, il seguente file .bashrc è configurato per impostare la variabile d’ambiente DATAPATH e un alias:

# .bashrc # Source global definitionsif ; then . /etc/bashrcfi # User specific environmentPATH="$HOME/.local/bin:$HOME/bin:$PATH"export PATH # Uncomment the following line if you don't like systemctl's auto-paging feature:# export SYSTEMD_PAGER= # User specific aliases and functionsexport DATAPATH=/data/filesalias l="ls -lt"

1.13 Scrivere script di shell

Finora ci siamo concentrati esclusivamente sulla natura interattiva della shell Bash. Per interattivo intendiamo inserire manualmente i comandi al prompt uno per uno ed eseguirli. In realtà, questa è solo una piccola parte di ciò che la shell è in grado di fare. Probabilmente uno degli aspetti più potenti della shell riguarda la capacità di creare script di shell. Gli script di shell sono essenzialmente file di testo contenenti sequenze di istruzioni che possono essere eseguite all’interno dell’ambiente di shell per eseguire compiti. Oltre alla capacità di eseguire comandi, la shell fornisce molti dei costrutti di programmazione come i cicli for e do e le istruzioni if che ci si potrebbe ragionevolmente aspettare di trovare in un linguaggio di scripting.

Purtroppo una panoramica dettagliata dello scripting di shell va oltre lo scopo di questo capitolo. Ci sono, comunque, molti libri e risorse web dedicate allo scripting di shell che rendono giustizia all’argomento molto più di quanto potremmo mai sperare di fare qui. In questa sezione, quindi, forniremo solo un piccolo assaggio dello scripting di shell.

Il primo passo nella creazione di uno script di shell è quello di creare un file (per gli scopi di questo esempio lo chiameremo semplice.sh) e aggiungere il seguente come prima linea:

#!/bin/sh

Il #! è chiamato “shebang” ed è una speciale sequenza di caratteri che indica che il percorso dell’interprete necessario per eseguire lo script è il prossimo elemento sulla linea (in questo caso l’eseguibile sh situato in /bin). Questo potrebbe anche essere, per esempio, /bin/csh o /bin/ksh se uno dei due fosse l’interprete che vuoi usare.

Il prossimo passo è scrivere un semplice script:

#!/bin/shfor i in *do echo $idone

Tutto quello che fa questo script è iterare tutti i file nella directory corrente e visualizzare il nome di ogni file. Questo può essere eseguito passando il nome dello script come argomento a sh:

$ sh simple.sh

Per rendere il file eseguibile (negando così la necessità di passarlo al comando sh) si può usare il comando chmod:

$ chmod +x simple.sh

Una volta impostato il bit di esecuzione sui permessi del file, esso può essere eseguito direttamente. Per esempio:

$ ./simple.sh

1.14 Riassunto

In questo capitolo di Ubuntu Essentials abbiamo fatto un breve tour dell’ambiente shell Bash. Nel mondo degli ambienti desktop grafici è facile dimenticare che la vera potenza e flessibilità di un sistema operativo può spesso essere utilizzata solo scendendo sotto l’interfaccia desktop user friendly e utilizzando un ambiente shell. Inoltre, la familiarità con la shell è una necessità quando si richiede di amministrare e mantenere sistemi basati su server che non hanno il desktop installato o quando si cerca di riparare un sistema che è danneggiato al punto che il desktop o l’interfaccia Cockpit non si avvia più.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.