domenica 19 giugno 2011

Linux Bash Scripting for dummies: Bash vs Shell (parte 1)

Ciao e benvenuto nella prima uscita della nuova rubrica settimanale che ci siamo preposti di fare, come puoi vedere dal titolo questa guida è rivolta al più ampio bacino d’utenza possibile, soprattutto ai cosiddetti newbie, coloro che cioè si stanno avvicinando a Linux da poco tempo e – naturalmente – si trovano un pò spaesati, soprattutto se abituati al mondo Windows.



Quello che oggi andremo a vedere è lo strumento principale che ci accompagnerà durante tutto il viaggio, la shell, l’obiettivo della rubrica è fornire degli strumenti e dei tip&tricks all’utente per consentirgli di padroneggiare la shell in modo corretto e perché no, fornire ulteriori spunti di approfondimento per il futuro, chi sà che non mi diventerai un sistemista pure tu :D

Bash vs Shell: Introduzione e definizione


Prima di tutto, cos’è la shell? e perché in molti la chiamano bash? Bene prima di rispondere ti invito a guardare questa orrenda immagine qui sotto…



Se proprio vuoi farti del male puoi anche cliccarci su per ingrandirla, ma assicurati di averlo fatto a stomaco vuoto. Dicevamo, quello che vedi qui sopra è il flusso che parte dall’utente e finisce sull’hardware del pc, quando diamo un comando su linux questo parte da noi (utente), passa per la struttura del sistema operativo Linux (shell, sistema op. e poi kernel) per poi finire sull’hardware del pc su cui lo stiamo eseguendo.

Noterai che la struttura del sistema operativo non è lineare, si dice infatti che Linux sia un sistema operativo “a cipolla”, l’utente cioè comunica con lo strato più esterno – la shell – che interpreta i comandi da passare allo strato successivo, il sistema operativo con tutto il software installato, i moduli ecc…che poi vengono passati al kernel che è il cuore di Linux, il quale a sua volta esegue il comando sull’hardware della macchina terminando il flusso.

Avrai capito quindi che la shell non è altro che un interfaccia tra il mondo esterno ed il sistema operativo, o più esattamente un interprete, perché deve “tradurre” i comandi che noi impartiamo in linguaggio binario per il sistema operativo ed il kernel.

Ma la bash? dov’è nello schema qui sopra?

Non c’è! semplicemente perché bash è una shell, ovvero un evoluzione della stessa. Quando nacquero i primi sistemi operativi UNIX (Linux si dice che è un sistema operativo UNIX-Like, perché deriva da esso) l’unico modo per l’utente di comunicare con i strati sottostanti era la shell, che possiamo definire come una versione molto primitiva della bash, già perché bash non è altro che un acronimo (B.A.SH): Bourne Again SHell, cioè “un altra bourne shell”.

Stephen Bourne è un informatico britannico, nel 1970 lavorava presso una società chiamata AT&T e fu allora che iniziò a sviluppare la SH (shell è più comunemente chiamata con la sua contrattura “sh”) per poi rilasciarla definitivamente nel 1978, sh diventò poi l’interfaccia testuale predefinita dei sistemi unix a partire dalla versione 7 in poi (andando a sostituire la Thompson shell).

In seguito due informatici, Brian Fox e Chet Ramey, iniziarono a sviluppare un evoluzione della sh, andando a creare appunto la bash; dal punto di vista della programmazione, bash ha in più rispetto all’sh il supporto alla personalizzazione ed un ambiente di programmazione completo come la definizione di funzioni e il supporto alle operazioni matematiche a numeri interi.

Ci sono altri tipi di shell oltre alla bash, le quali verranno solo menzionate visto che molte sono quasi in disuso ed inoltre nei sistemi Linux odierni la shell predefinita è la bash; queste sono la csh (C shell), tclsh (Tcl Shell), Ksh (Korn Shell, insieme alla bash la più diffusa nei sistemi *BSD), ash (A shell), zsh (Z shell).

Hint: Apri con un editor di testo il file “/etc/passwd”, ti ritroverai una roba simile a questa:

1 2 3 4 5 
apache:x:48:48:Apache:/var/www:/bin/bash mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash morfeus:x:500:501:Il Portalinux Blog:/home/morfeus:/bin/sh webalizer:x:67:67:Webalizer:/var/www/usage:/sbin/nologin memcached:x:100:101:Memcached daemon:/var/run/memcached:/sbin/nologin

cerca il tuo nome utente all’interno del file e cambia l’ultimo parametro (ogni parametro viene diviso dal successivo dai “:”), questo parametro definisce quale tipo di shell l’utente in questione deve avere al suo login. Quasi sicuramente avrai “/bin/bash”, prova a mettere “/bin/sh” ed apri un altra shell, noterai che il prompt dei comandi cambierà da cosi

[morfeus@kratos ~]$

a cosi

-sh-3.2$

in questo momento stai utilizzando l’interprete “shell” al posto del “bash”.

Ti ho volutamente illustrato il metodo più lungo per farti dare un occhiata al file “passwd”, li dentro troverai tutto quello che riguarda gli utenti installati sul tuo sistema, il metodo più veloce per fare questa stessa prova è lanciare il comando “/bin/sh” se si sta usando la bash oppure “/bin/bash” se viceversa si sta usando sh.:)

NB. Se stai usando Ubuntu quasi sicuramente /bin/sh è un link simbolico a /bin/bash, questo perché Ubuntu installa di default solo la bash, in questo caso questo cambiamento non avrà effetto sul tuo sistema, prova a scaricarti la iso di una Centos 5 ed instàllatela su una macchina virtuale, Centos fornisce sia sh che bash e quindi potrai provare con le tue mani.

BASH: Script, Operatori e Metacaratteri

Uno dei principali vantaggi che si è avuto con l’sh è che con l’introduzione di essa si è avuto un vero e proprio interprete per i cosiddetti scripts, una lista di comandi inseriti all’interno di un file di testo che, una volta reso eseguibile e richiamato, vengono lanciati in sequenza.

Prima di iniziare a produrre i primi script però dobbiamo sapere cosa ci consente di fare la bash, ovvero dobbiamo iniziare a vedere i comandi che si possono lanciare, cosa fanno, e come si gestiscono.

NB. Per semplicità da ora in poi scriverò shell intendendo l’interprete “bash”, quando ti parlerò della shell “sh” lo specificherò appositamente e la chiamerò appunto con “sh”.

Bash fa uso di alcuni caratteri che vengono classificati come metacaratteri, questi metacaratteri consentono di gestire i comandi in vari modi, per esempio, due operandi molto usati nella quotidianità dell’uso di bash sono l’asterisco ed il punto interrogativo:

  • *: “Qualsiasi stringa di caratteri”
  • ?: “UN carattere qualsiasi”

quindi se noi all’interno di una cartella abbiamo un contenuto del tipo:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
:~$ ls   arch                  dd             hostname    nice           stty awk                   df             igawk       nisdomainname  su basename              dmesg          ipcalc      pgawk          sync bash                  dnsdomainname  kill        ping           tar cat                   doexec         link        ping6          taskset chgrp                 domainname     ln          ps             touch chmod                 echo           logger      pwd            tracepath chown                 egrep          login       raw            tracepath6 cp                    env            ls          rm             true cpio                  ex             mkdir       rmdir          umount cut                   false          mknod       rpm            uname date                  fgrep          mktemp      rvi            unlink dbus-cleanup-sockets  gawk           more        rview          usleep dbus-daemon           grep           mount       sed            vi dbus-monitor          gtar           mountpoint  sh             view dbus-send             gunzip         mv          sleep          ypdomainname dbus-uuidgen          gzip           netstat     sort           zcat

e lanciamo il comando “ls ?name”, diciamo a Linux di listarci tutti i file all’interno della cartella che hanno UN qualsiasi carattere che precede “name” nel nome, e quindi avremo come unico risultato “uname”, se invece lanciamo “ls *name” contrariamente diciamo a Linux di listarci tutti i file che hanno una qualsiasi stringa di caratteri che precede “name” nel nome, e quindi come risultato avremo:

1 2 3 
basename       domainname  nisdomainname  ypdomainname   dnsdomainname  hostname    uname

Oltre ai metacaratteri abbiamo anche i cosiddetti operatori, in bash abbiamo due operatori che vengono chiamati set ed unset.

Questo operatori ci consentono di definire un insieme congiunto o disgiunto di caratteri, per esempio l’operatore [a-t] indica l’insieme dei caratteri minuscoli (te lo ricordi che Linux è case sentitive si?) che vanno dalla a alla t, per indicare insiemi disgiunti invece si usa la virgola, quindi con [a-d,t-z] indichiamo gli insiemi di caratteri minuscoli che vanno dalla “a” alla “d” e dalla “t” alla “z”, infine possiamo definire singoli caratteri semplicemente specificandoli separatamente all’interno dell’operatore: [aeiou] indica tutte le vocali singolarmente; prendendo come esempio sempre il contenuto che abbiamo visto sopra lanciando “ls b[aeiou]*” diremo che vogliamo il listato di tutti i file che iniziano per “b” e che hanno a seguire una qualsiasi stringa di caratteri che inizia con una vocale, e quindi avremo:

1 
basename  bash

Viceversa se vogliamo settare un operatore negativo basta inserire un punto esclamativo all’inizio dell’operatore, quindi se con [aeiou] intendiamo “tutte le vocali” con [!aeiou] intendiamo “tutto TRANNE le vocali“.

Ci sono altri metacaratteri che si usano in bash, qui te ne illustro alcuni, i più semplici, in una semplice lista, fermorestando che più avanti quando inizieremo a vedere i primi scripts capiremo come usarli meglio, mentre nella prossima pagina ne vedremo più approfonditamente altri:

  • < : redirezione dell’input, usato molto per passare ad uno script od un comando un file/variabile/qualsiasi cosa con, magari, una lista di configurazioni o con altri comandi da essere eseguiti a loro volta;
  • > : redirezione dell’output, usato per stampare il risultato di un comando su un file1 piùttosto che a schermo come avviene normalmente.
  • & : Esegue il comando in background, quando lanciamo un comando questo prende possesso della shell fino alla fine della sua esecuzione, potremmo avere la necessità di lanciare un comando che prevede una esecuzione abbastanza lunga e quindi per non dover aspettare il termine dell’esecuzione possiamo passare “&” alla fine del comando per, appunto, farlo girare in background e continuare ad usare la shell durante l’esecuzione.
  • ; : separatore, con la shell possiamo lanciare più comandi in sequenza separandoli con un punto e virgola, in questo modo diciamo alla shell di lanciare il comando successivo al termine dell’esecuzione di quello precedente, a prescindere dal risultato di questo.
  • && : separatore, con questo operatore possiamo lanciare ancora una volta una serie di comandi in sequenza ma solo se viene soddisfatta una condizione particolare, ovvero che l’esecuzione del comando precedente sia terminata con stato positivo, cioè senza errori che ne hanno interrotto l’esecuzione improvvisamente. Svolge la medesima funzione del punto e virgola tranne che, appunto, per la verifica del cosiddetto “exit code”2 del comando.
  1. od un device speciale, vedremo più avanti di cosa si tratta []
  2. ogni comando in Linux resituisce un codice al termine dell’esecuzione, per indicare in che modo questa si è conclusa. Se un comando termina correttamente senza errori restituirà il codice 0 (zero), se ci sono stati errori restituirà il codice 1, mentre se è stato interrotto a causa di un altro avvenimento, che non è un vero errore, restituirà il codice 2 che significa “unknown” []
da http://www.ilportalinux.it/linux-bash-scripting-for-dummies-bash-vs-shell/

Nessun commento: