M06 UF2:  Automatització de tasques i llenguatges de guió
ASIX-2
GNU/Linux
Arxius de guió dels bash de Linux (Part 1)
18/03/21

Pràctica 2: Arxius de guió del bash de Linux (Part 1)

LLIURAMENT PRÀCTICA 2

Scripts a enviar per alumne:  Aquí
Data Límit:
28-3-2020  a les 23.59.59
Publicació de solucions: 29-3-2021
Correu:
cf@collados.org
Assumpte: asix2_cognom_nom_m06uf2pr2
Missatge: URL de Github d'un dipòsit de nom asix2_cognom_nom_m06uf2pr2
 
DOCUMENTACIÓ

0- Referències
1- http://www.tldp.org/LDP/abs/html/index.html
2- http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html
3- http://linuxconfig.org/bash-scripting-tutorial
4- https://www.shellscript.sh/


1- El  "shebang"

El shebang en linux correspon a el conjunt de caràcter #! el quals són utlitzats pel sistema per saber que el fitxer és un script (arxiu de guió) i que a continuació s'indica quin és l'interpret utilitzat per executar el script. El shebang s'ha d'escriure sempre al principi de qualsevol script. Així doncs, pel cas de scripts que han de ser executats per bash (interpret d'ordres de Debian, Ubuntu, Red Hat....) qualsevol arxiu de guió hauria de començar per:

#! /bin/bash

2- Definició de variables del shell

a)
Són variables definides per l'usuari des del shell de Linux, i que poden ser utilitzades en qualsevol moment per desarr dades. Una variable no és res més que una paraula (cadena de caràcters) a la qual assignem un valor que podria ser un nombre, nom de directori, nom de fitxer, nom de dipositiu, un caràcter, una cadena de caràcters i qualsevol altre tipus de dada.

b)
Una variable ha de definir-se abans de poder ser utilitzada, donant-li un nom i indicant a que és igual. El nom d'una variable ha de complir les següents normes:
     *Ha de incloure lletres o nombres o _
     *No pot començar amb un nombre
     *No admet els caracters &, ! i espai en blanc
     *No pot tenir més d'una paraula.

c)
Una variable es defineix així:
    nom_variable=valor_variable


d)
Exemples:
    cadena=hola
    dada=5
    nom="Joan Pérez"

e)
Per cridar al contingut d'una variable s'ha posar al davant el signe $. Si ara escrivim echo $nom, veurem per pantalla la paraula hola.Si fem que dirusr=/home/usuari, llavors cd $dirusr ens portarà al directori /home/usuari.


3- Varables de sistema i delimitadors de cadenes.

Alguns caracters són especials, poden ser problemàtics i cal delimitar-los. Els caracters especials amb els quals podem tenir problemes i cal delimitar són els següents: ? * . [] & $ i l'espai en blanc. Els 2 delimitadors més importants són les cometes i l'apòstrof.

a) Delimitació de caracters amb cometes.

Poden delimitar tots els caracters especials, menys $.Exemple:
name=Pere
nom="Hola, soc $name"
echo $nom

Per pantalla sortirà => Hola, soc Pere

b)
Delimitació de caracters amb apòstrof
Delimiten tots els caracters, inclòs $. Exemple:
name=Pere
nom='Hola, soc en $name'
echo $nom

Per pantalla sortirà => Hola, soc en $name


4- echo

Escriu a continuació la cadena de caràcters que li passem com a paràmetre i fa el canvi de línia. Especialment útil per treballar amb fitxers de guió. Les " i ' són caràcters delimitadors que s'utilitzen normalment amb echo.

Exemples:

echo Hola  ---> retorna Hola
echo "Hola món"  ---> retorna Hola món
nom_usuari=Pere
echo "Hola $nom_usuari"
---> retorna Hola Pere
echo 'Hola $nom_usuari' ---> retorna Hola $nom_usuari

Si no volem realitzar canvi de línia hauriem d'utilitzar el paràmetre -n. Exemple:

echo -n "Dóna el primer valor de la multiplicació: "


5- read

a) Amb l'ordre read, tot allò que s'introdueixi des de teclat serà assignat a una variable. És equivalent a fer un scanf del llenguatge C.

b) Si volem tractar els caràcters especials com per exemple $, *, ? / [ \ ] ( ) < > >>, com a caràcters normals , llavors els hem de delimitar amb cometes o apotrof.

c) Per demanar a l'usuari dades per teclat es pot fer això:

echo -n  "Dona opció:"
read opcio

d) Si volem utilitzar l'ordre read per introduir una contrasenya, hem d'utilitzar l'opció -s de l'ordre. Per exemple:

echo -n "Escriu la contrasenya de l'usuari: "
read -s CTSNYA


6- Avaluació aritmètica

a) Amb bash podem fer les operacions aritmètiques  +   -   /  *  **  ++  --  <  >  <=  >=  !=  ==. Quan es fan comparacions el valor serà 0 si és veritat i 1 si és fals.

b) El resultat d'una comparació s'ha de buscar dins de la variable $?.

c) És molt important delimitar les operacions dins de $((   )).

Exemple 1
a=4
b=5
c=$(( b + a ))
echo $c

9

Exemple 2
a=4
b=5
(( b >= a ))
echo $?

 0 (és veritat)

Exemple 3
a=4
b=5
$(( b != a ))
echo $?

 0 (és veritat)

Exemple 4
a=4
b=5
$(( b == a ))
echo $?

 1 (és mentida)

Exemple 5
a=7
(( a++ ))
echo $a

8


NOTA: Els espais en blanc no són importants però val la pena manternir-los!!!


7
- Avaluació directa de cadenes

a) Amb bash podem fer les següents comparacions de cadenes >  <  <=  >=  !=  ==.
b) Quan es fan comparacions el valor de $? serà 0 si és veritat i 1 si és fals.
c) Les comparacions in ordre alfabètic segons el codi ASCII.
d) Es delimiten les comparacion dins de [[  ]]
e) Dins de [[  ]] cada variable necessita el $ al davant per indicar que volem treballar amb el seu contingut.
f) Ha d'haver espais en blanc obligatoris entre [[ i la primera variable.
g) Ha d'haver espais en blanc obligatoris entre ]] i la segona variable.
h) Millor un espai en blanc entre les variables i el comparador.
i) El resultat de la comparació s'ha de buscat dins de la variable $?.

Exemples:

a=hola

b=adeu

[[   $a   ==   $b ]]

echo $?

1   (és mentida)

a=hola

b=adeu

[[  $a  <  $b  ]]

echo $?

1   (és mentida)

a=hola

b=adeu

[[  $a  >  $b ]]

echo $?

0   (és veritat)

a=hola

b=adeu

[[  $a  ==  $b  ]]

echo $?

1   (és mentida)

a=hola

b=adeu

[[  $a  !=  $b  ]

echo $?

0   (és veritat)

a=hola

b=hoa

[  $a  !=  $c  ]

echo $?

1   (és mentida)


NOTA:
Els espais en blanc són importants!!!



8- Avaluació de fitxers

a) Té moltes opcions. Millor anar a el manual amb man test. Una de les opcions més important és -e que ens permet saber si un fitxer existeix o no.

Exemple:   [[  -e   nom_fitxer   ]]

Si existeix el fitxer, l'ordre ens retorna 0 dins de la variable $?, i un 1 si no existeix. Dins del nom del fitxer s'ha d'incloure el directori a on es troba.

b) Una altra opcio important és -s que retorna un 0 dins de la variable $? si un fitxer existeix i té una mida diferent a zero bytes.

c) Amb l'opció -d, ens diu si existeix o no un director. Ens diu que és 0 (veritat) si existeix el directori. Compte, que si existeix però no és un directori retorna fals, igual que si no existeix.

Exemple:  [[ -d  nom_directori ]]

d) [[ !  -e  nom_fitxer ]] retorna 0 si és veritat que el fitxer no existeix, i retorna 1 (mentida) si el fitxer existeix.

e) [[ !  -d  nom_fitxer ]] retorna 0 si és veritat que el directori no existeix, i retorna 1 (mentida) si el directori existeix.

NOTA: Els espais en blanc són importants!!!

12- Operacions AND, OR i NOT amb números

a) Operació lògica AND  -->  &&

b) Operació lògica OR  -->  ||

c) Operació lògica NOT  -->  !

Exemple:

a=5

b=3

c=6

(( b < a )) && (( c > a ))

echo $?

0 (és veritat)

a=5

b=6

c=4

(( b < a )) || (( c > a ))

echo $?

1 (és mentida)

a=7

b=6

!(( b < a ))

echo $?

1 (és mentida)

NOTA: Els espais en blanc no són importants però val la pena manternir-los!!!


9- Operacions AND, OR i NOT amb cadenes

a) Operació lògica AND  -->  &&

b) Operació lògica OR  -->  ||

c) Operació lògica NOT  -->  !

Exemple:

a=jordi

b=carles

c=francisco

[[  $a  >  $b  ]]  &&  [[  $b  <  $c  ]]

echo $?

0 (és veritat)

a=carles

b= jordi

c=francisco

[[  $a  >  $b  ]]  ||  [[  $b  <  $c  ]]

echo $?

1 (és mentida)

a=carles

b=jordi

! [[  $b  <  $a  ]]

echo $?

1 (és mentida)

NOTA: Els espais en blanc són importants!!!!!!!!!!!!!!!


10- Ordre if-then-else-fi


Comprova si una ordre ha estat executada amb èxit o si una expressió és correcta. En cas de que el resultat de la comprovació sigui veritat, executa una sèrie d'ordres, i si és falsa, n'executa unes altres. Funciona bàsicament igual que if-else de C. L'ordre then és equivalent a i  l'ordre  fi  }. També permet avaluar l'èxit o fracàs de l'execució d'una ordre del bash shell.

Estructura:
if ordre_o_expressió_linux
then
    ordre_linux_1
    ordre_linux_2
    ordre_linux_3
    ....................

else
    ordre_linux_N
    ordre_linux_N+1
     ....................

fi

Exemple 1:

Fes un arxiu de guió que ens permeti fer un llistat del directori en el qual es troba l'usuari, amb dues opcions: a) Veure mida dels fitxers b) Veure totes les característiques dels fitxers.

#!/bin/bash
echo "Escriu s per llistar el directori amb la mida dels arxius"
echo "Escriu l per llistar totes les característiques dels arxius"
read opc
if  [[  $opc  ==  "s"  ]]
then
    ls -s
else
    ls -l
fi
exit 0


Exemple 2:


Fes un arxiu de guió que ens permeti comprova si un fitxer existeix o no.

#!/bin/bash
echo "Escriu el nom del fitxer: "
read nom
if  [[  -e  $nom  ]]
then
    echo "El fitxer $nom existeix"
else 

    echo "El fitxer $nom no existeix"
 fi
exit 0


Exemple 3:

Fes un arxiu de guió que ens permeti fer un llistat del directori en el qual es troba l'usuari, amb dues opcions: a) Veure mida dels fitxers b) Veure totes les característiques dels fitxers.

#!/bin/bash
echo "Escriu s per llistar el directori amb la mida dels arxius"
echo "Escriu l per llistar totes les característiques dels arxius"
read opc
if  [[  $opc  ==  "s" ]]
then
    ls -s
else
    ls -l
fi
exit 0


Exemple 4:


Fes un arxiu de guió que mostri el missatge "Valor negatiu" si un nombre donat per l'suari és menor a 0 i que mostri el missatge "Valor positiu" si el valor donat és més gran o igual a 0

#!/bin/bash

echo "Escriu la quatitat:"
read num
if   (( num >= 0 ))
then
    echo "El valor és positiu"
else
   
echo "El valor és negatiu"
fi
exit 0


11- Ordre case-in-esac


a)
Permet escollir entre des o mes camins d'execució d'ordres alternatius.
b)
La selecció es fa comparant un valor_comparat amb diversos valors_de_comparació. Quan el valor_comparat coincideix amb un valor_de_ comparació, llavors, s'executen les ordres associades a aquest valor_de_comparació.
c)
L'equivalent a default de C, és *
d)
Sempre finalitza amb esac.

Estructura: 
case valor_comparat in
    valor_de_comparació_1)  ordre
                                                    ordre;;

    valor_de_comparació_2) ordre
                                                    ordre
                                                  ordre;;

    valor_de_comparació_3) ordre;;

    ..........................................
    ..........................................

    *)  ordre_per_defecte
        ordre_per_defecte;;
esac


Exemple 1:


#!/bin/bash
echo " a) Llistat del directori /home/pere"
echo " b) Llistat del directori /home/joan"
echo " c) Llistat del directori /home/anna"
echo " d) Llistat del directori /home/maria"
read opc
case $opc in
    a) ls -ls /home/pere;;
    b) ls -ls /home/joan;;
    c) ls -ls /home/anna;;
    d) ls -ls /home/maria;;
    *) echo "Opció incorrecta";;
esac
exit 0


Exemple 2:


#!/bin/bash
case "$1" in

     'start')
            
/usr/app/startup-script
            ;;

     'stop')
             /usr/app/shutdown-script
             ;;
     'restart')
             echo "Usage: $0 [start|stop]"
             ;;
esac
exit 0


Exemple 3:


#!/bin/bash
a=
7
case "$a" in
     [0-4]) echo "No aprovat";;
    [5-6]) echo "Aprovat";;
    [7-8]) echo "Notable";;
    9|10) echo "Excel·lent";;

esac
exit 0


12- Ordre while-do-done


* Executa ordres_linux mentre es compleixi ordre_o_expressió_linux. Sempre acaba amb done. Abans d'entrar en el llaç s'avalua la condició d'entrada.

* Potser no s'executen mai les instruccions dins del bucle

* Estructura:
while ordre_o_expressió_linux
do
    ordres_linux
done


Exemple 1

#!/bin/bash
a=1
while
(( a <= 4 ))
do
    b=$(( a * 2 ))
    echo $b
    a=$(( ++a ))

done
echo "Adéu i fins una altra ocasió"
exit 0

El resultat serà:
2
4
6
8
Adéu i fins una altra ocasió


Exemple 2

#!/bin/bash
opc=s
while [[  $opc  !=  n  ]]
do
    clear
    echo -n "valor 1: "
    read v1
    echo -n "valor 2: "
    read  v2
    suma=$(( v1 + v2 ))
    echo -n "La suma de $v1 + $v2 és: $suma"
    echo
    echo -n "Vols continuar (s/n): "
    read opc
done
exit 0


13- Ordre until-do-done


* Executa ordres_linux mentre es compleixi ordre_o_expressió_linux. Sempre acaba amb done. Abans d'entrar en el llaç s'avalua la condició d'entrada.

* S'executen com a mínim una vegada les instruccions dins del bucle

* Estructura:
until
condició

do

    ordres_linux

done


Exemple 1:


#!/bin/bash
a=8
until (( $a <= 4 ))

do
   
b=$(( a * 2 ))
    echo $b
    a=$(( --a ))

done
echo "Adéu i fins una altra ocasió"
exit 0


14- Ordre for-in do-done


Estructura:
for variable in llista
do
    ordres_linux
done

Funciona de la següent manera:
1r) Assigna a variable al primer valor de llista
2n) Executa ordres_linux
3r) Assigna variable al següent valor de la llista
4t) Executa ordres_linux
5è) Torna al 3r pas fins que s'acabin les variables de la llista.

Exemple 1:


for 
in  script.sh  dades.pdf   document.odt
do
    gzip $a
done
echo "Fitxers comprimits"

Comprimeix tots els fitxers que hi ha  a la llista i que es trobin al directori de treball actual.

Exemple 2:


for  in  *.gz
do
    gzip  -d  $a
done
echo "Fitxers descomprimits"

Descomprimeix tots els fitxers amb extensió .gz que es trobin al directori de treball actual.


Exemple 3

for a in 1 2 3 4
do
    b=$(( a * 2 ))
   
echo $b
done

El resultat serà:
2
4
6
8                                                                        

Exemple 4


for 
in  {1..5}   #
{START..END}
do 
    b=$(( a * 2 ))
   
echo $b
done

El resultat serà:
2
4
6
8       
10                                                                                 

Exemple 5


for 
in  {1..9..2}  #
{START..END..INCREMENT}
do
    b=$(( a * 2 ))
 
   echo $b
done

El resultat serà:
2
6
10


Exemple 6


for 
in  {1..10..4} 

do
    b=$(( a * 2 ))
 
   echo $b
done

El resultat serà:
2
10
18

Nota: Només farà 1, 5 i 9.                                     


Exemple 7

#!/bin/sh
logfile="/var/log/messages"
for mon in Sun Mon Tue Wed Thu Fri Sat
do
   grep $mon $logfile > $logfile.$mon
done
exit 0

El resultat serà un fitxer de log diferent per cada dia de la setmana, a partir del fitxer de log general /var/log/messages

19- Ordre  exit

exit n: Finalitza l'execució de l'arxiu de guió del bash shell, i assigna el valor n com a codi de retorn (que normalment serà un zero si tot ha anat bé, i diferent de zero en cas contrari).

PRÀCTICA


1- 
Desenvolupa un script que ha de baixar un fitxer de nom usuaris.ods d'aquest enllaç: http://www.collados.org/asix2/m06/uf2/pr2/usuaris.ods. A continuació el programa ha de convertir el fitxer .ods en un fitxer de texte pla .csv amb l'ajut que trobaràs a (1) o també a (3). Amb la llista d'usuaris en format .csv i l'ajut que trobaràs a (2), has de crear un usuari del sistema per cada usuari de la llista amb un nom d'usuari igual al de la llista i que sigui membre per defecte del grup users.  Comença  el número UID a partir del 3001 per seguretat. La resta de dades és al teu criteri personal. Si l'arxiu de guió finalitza correctament i amb èxit,  assignarà el valor 0 com a codi de retorn. El nom del script serà mltusr.sh.

2-  Mira la nota (4). Desenvolupa un script per l'usuari root que faci la configuració bàsica d'un servidor DHCP. El programa ha de fer les següents tasques:

El nom de l'arxiu de guió serà dhcpd.sh.

3-
Desenvolupa un script per l'usuari root que demani totes les dades necessàries per crear un nombre N d'usuaris. El programa ha de:
4- Fes un arxiu de guió de l'interpret d'ordres bash shell per l'usuari root que copiï el fitxer resolv.conf que es troba a /etc  dins d'una carpeta del directori personal de root, el nom de la qual, has de passar com a paràmetre. Si la carpeta no existeix, l'arxiu de guió ha d'enviar un missatge a root, avisant-lo de que la carpeta no existeix, i preguntar-li si està segur de crear la carpeta. En el cas de que l'usuari root confirmi  la creació de la carpeta, l'arxiu de guió haurà de crear-la i continuarà la seva execució. En el cas de que l'usuari root no  ho confirmi, l'arxiu de guió deixarà d'executar-se, i tornarà a l'interpret d'ordres, assignant el valor 1 com a codi de retorn. Si l'arxiu de guió continua la seva execució, llavors farà una còpia de seguretat de resolv.conf amb el nom resolv.conf.backup.data a on data és el any, mes, dia, hora i minut de la realització de la còpia de seguretat (7). A continuació, el fitxer serà comprimit i s'btindrà el fitxer resolv.conf.backup.data.gz, i l'original resolv.conf.backup.data serà esborrat i també la còpia de resolv.conf que hi ha dins de la carpeta de l'usuari. L'arxiu de guió ha de finalitzar assignant el valor 0 com a codi de retorn si ha arribar al final amb èxit. El nom de l'arxiu de guió serà resolv.sh.

5- Fes un arxiu de guió de l'interpret d'ordres bash shell que pugui executar qualsevol usuari del sistema i que tingui les següents caracterísitiques:
Si escollim l'opció -e amb l'extensió i carpeta llavors, tots els arxiu que tingui la extensió indicada dins de la carpeta escollida seran moguts a una carpeta de nom paperera dins del directori personal de l'usuari. Si la carpeta paperera no existeix, l'arxiu de guió crearà la carpeta sense haver de donar cap avís a l'usuari. Si no hi ha cap fitxer amb l'extensió indicada llavors el programa enviarà a l'usuari el missatge "Els fitxers amb l'extensió indicada no existeixen", no farà res més, i finalitzarà de manera normal. Si la carpeta indicada no existeix, llavors el programa enviarà a l'usuari el missatge  "La carpeta indicada no existeix" , no farà res més, i finalitzarà de manera normal.

Si escollim l'opció -r, llavors
el programa esborrarà tots els arxius de la paperera (però, no esborrarà la carpeta). Si escollim l'opció -r i la paperera no existeix, llavors el programa enviarà a l'usuari el missatge "La paperera encara no existeix", no farà res més i finalitzarà de manera normal.

Un cop finalitzat el programa, s'eviarà al sistema el codi de retorn 0.
El nom de l'arxiu de guió serà esb.sh.

6- Mira la nota (7). Fes un arxiu de guió  de l'interpret d'ordres del bash shell que:


NOTES

(1)  Utilitza les opcions --headless i --convert-to de l'ordre libreoffice. En l'opció --convert-to no cal posar cap filtre. El filtre per defecte funciona. Per internet trobaràs exemples de conversió. També al man de l'ordre libreoffice.
(2)
https://shapeshed.com/unix-cut/ --> Compte amb els espais en blancs dels exemples!!!!!!
     Exemple: cut  -d  "  "  -f  2   --> Aconseguiria el 3n tall d'una cadena utilitzant  espai en blanc com a separador.  Per exemple de "Benvinguts tots els estudians" aconseguiria el tall tots.
(3) http://www.unix.com/shell-programming-and-scripting/154969-access-ods-files.html
(4) Recordeu  l'utilitat dels símbols > i >> .
(5) Amb aptitude search pwgen podem saber i està instal·lat o no el paquet.
(6)
És fàcil afegir la data (any, mes, dia, hora, minut) al nom d'un fitxer. Si volem crear una variable de sistema que tingui el nom d'un fitxer  la data del moment de creació, podem fer això:
 data=`date +20%y%m%d%H%M`

 nom_fitxer=etcssh.$data
Si executem aquestes ordres per exemple, el 3 d'octubre del 2017 a les 16.00,  llavors es crearà una variable de sistema de nom nom_fitxer, i el seu contingut serà etcssh.201710031600.
(7) Aquí tens un enllaç que explica els operadors per treballar amb fitxers.