Linux e la linea di comando, comandi particolari e poco conosciuti: Bash, comandi interni alla shell

1

linux

La linea di comando e più propriamente la console bash rappresentano lo strumento di cui ogni sistemista Linux non può fare a meno. Modificare file, elaborare contenuti ed operare sui processi sono parte del lavoro quotidiano di chiunque gestisca sistemi informatici più o meno ampi.
Interessante è capire come esistano moltissimi comandi a disposizione di un sistemista oltre a quelli comunemente usati che, per quanto ignorati, possono facilitare il lavoro quotidiano.
Questo primo articolo cerca di effettuare una panoramica ricca di esempi di come sia possibile utilizzare comandi incorporati della shell come set, declare, type e molti altri.

Comandi interni alla shell

La prima panoramica riguarda i comandi interni alla shell. Caratteristica di questi comandi è di non avere binari corrispondenti installati nel sistema (in directory come /bin, /sbin, /usr/bin e così via), infatti è l’ambiente erogato dall’eseguibile bash (a sua volta un binario installato nel sistema) a renderli disponibili.

set

Il comando set permette di modificare molti comportamenti e funzionalità della bash. Per abilitare una funzionalità si antepone all’opzione interessata un carattere “-“, viceversa per disabilitarla è sufficiente anteporre un carattere “+” all’opzione.
Lanciato senza parametri il programma restituisce le impostazioni generali della shell, comprensive di variabili e funzioni che si riferiscono all’ambiente.
Alcuni esempi di utilizzo di set:
Per fare in modo che le variabili create vengano automaticamente esportate è possibile attivare l’opzione “a”:

$ set -a
$ VARIABILE="VALORE"
$ bash
$ echo $VARIABILE
VALORE

Per fare in modo che i comandi lanciati all’interno del sistema siano stampati, sarà sufficiente attivare l’opzione “x”, prima dell’output di ogni comando successivo lanciato apparirà il comando effettivamente lanciato. Cosa questo significhi lo si capisce dal seguente listato:

rasca@anomalia:~$ set -x
++ echo -ne '\033]0;rasca@anomalia: ~\007'
rasca@anomalia:~$ ls
+ ls --color=auto
...
...

il comando lanciato è quindi in realtà un alias dello stesso con l’opzione “–color=auto”.

Le altre funzionalità relative al comando set si trovano nella voce omonima della man page del comando bash.

declare

Il comando declare è utilizzato per la dichiarazione delle variabili. Generalmente in bash una variabile viene dichiarata automaticamente con la sua definizione:

$ FOO=bar

dopodiché è utilizzabile con il nome $FOO. Il comando declare consente in fase di dichiarazione di specificare il tipo di variabile oltre che alcuni attributi inerenti al suo utilizzo.
Ad esempio, per dichiarare un array utilizzando il comando declare si utilizzerà l’opzione “-a”:

$ declare -a elementi=("primo" "secondo" "terzo")

mentre l’opzione “-i” dichiarerà una variabile di tipo integer:

$ declare -i numero=10

declare torna utile in fase di definizione anche per esportare automaticamente le variabili, attraverso l’opzione “-x”:

$ declare -x -i numero=10

questo comando ottiene lo stesso effetto di:

$ export numero=10

ma in più aggiunge anche la definizione del tipo. Infine, attraverso l’opzione “-r” è possibile rendere la variabile readonly, ossia non scrivibile all’interno della sessione.

NOTA: Le variabili di tipo array non sono esportabili a causa di un baco nella BASH (vedere la man page).

type

Il comando type può essere utilizzato per conoscere le caratteristiche relative agli argomenti passati. Attraverso l’opzione “-t” viene restituito il tipo di parametro passato:

$ type -t ls
alias
$ type -t /bin/ls
file
$ type -t echo
builtin
$ type -t set_prefix
function
$ type -t while  
keyword

E’ da notare la differenza tra “ls” e “/bin/ls”, rispettivamente un alias (relativo ad un file eseguibile) ed un file eseguibile. Ad un comando di tipo builtin non corrisponde necessariamente un file eseguibile, mentre le ultime due righe rappresentano rispettivamente una funzione disponibile nell’ambiente ed una parola chiave relativa al linguaggio bash.
Un’altra opzione supportata dal comando type è “-a” che indica tutte le corrispondenze al parametro passato. Ad esempio, relativamente ai comandi precedentemente esposti i risultati saranno i seguenti:

$ type -a echo
echo is a shell builtin
echo is /bin/echo
$ type -a ls  
ls is aliased to `ls --color=auto'
ls is /bin/ls
$ type -a set_prefix
set_prefix is a function
set_prefix () 
{ 
    [ -z ${prefix:-} ] || prefix=${cur%/*}/;
    [ -r ${prefix:-}CVS/Entries ] || prefix=""
}
$ type -a while     
while is a shell keyword

il comando echo viene indicato come interno e disponibile inoltre con l’eseguibile /bin/echo, lo stesso avviene per il comando ls per il quale viene indicata la definizione dell’alias oltre che il path del file effettivo. Infine la funzione set_prefix viene stampata nella sua interezza, mentre per while rimane l’indicazione di keyword.

exec

Il comando exec permette di lanciare un comando utilizzando il process ID (PID) della shell corrente. Questo significa che la shell verrà rimpiazzata dal comando, non generando un nuovo PID e comporta inoltre che il termine del comando corrisponderà con il termine della shell.
Ad esempio, se nell’ambiente grafico da una console viene lanciato il comando

$ exec xterm

alla chiusura della shell del programma xterm, anche la console verrà automaticamente chiusa.

jobs

Se il comando interno bg viene utilizzato per mandare un processo in background (cioè sullo sfondo del sistema e non in primo piano, mantenendone l’esecuzione) ed il comando interno fg viene utilizzato invece per mandare in foreground (quindi, in primo piano) un processo, il comando jobs permette di effettuare il listato dei processi e di conoscere informazioni relative a questi.
Supponendo di avere due script denominati script e script1 lanciati entrambi automaticamente in background attraverso il carattere speciale & alla fine dell’invocazione:

$ ./script &
[1] 28548
$ ./script1 &
[2] 29261

Sarà possibile conoscere lo stato dei processi in sospeso attraverso jobs:

$ jobs
[1]-  Running                 ./script &
[2]+  Running                 ./script1 &

Di questi attraverso l’opzione “-l” si potrà conoscere identificativo e PID:

$ jobs -l
[1]- 28548 Running                 ./script &
[2]+ 29261 Running                 ./script1 &

O solamente il PID:

$ jobs -p
28548
29261

Su tali processi sarà possibile effettuare operazioni di kill (considerando il PID):

$ kill 28548
$ 
[1]-  Terminated              ./script

Oppure operazioni di foregrounding/backgrounding, attraverso i già citati comandi interni fg e bg, considerando invece l’identificativo:

$ fg 2
./script1

Il tutto grazie ai dati resi disponibili dal comando interno jobs.

Conclusioni

I comandi interni alla bash illustrati e molti altri sono tutti ottimamente documentati all’interno della già citata man page della Bash ($ man bash), più propriamente nel capitolo “COMANDI INCORPORATI DELLA SHELL“.
Nella seconda parte di questo articolo verranno trattate utility di sistema come paste, tee, apropos e molte altre, generalmente poco utilizzate, ma di indubbio interesse.

Da sempre appassionato del mondo open-source e di Linux nel 2009 ho fondato il portale Mia Mamma Usa Linux! per condividere articoli, notizie ed in generale tutto quello che riguarda il mondo del pinguino, con particolare attenzione alle tematiche di interoperabilità, HA e cloud.
E, sì, mia mamma usa Linux dal 2009.