Laboratorio SISOP

58
2011 Michele Mariani Università degli Studi di Milano SISTEMI OPERATIVI Esame Laboratorio

description

Laboratorio SISOP

Transcript of Laboratorio SISOP

2011

Michele Mariani

Università degli Studi di Milano

SISTEMI OPERATIVI

Esame Laboratorio

Appunti strutturati come la modalità d’esame del Laboratorio di Sistemi Operativi tenuto dal professore

Monga nell’anno accademico 2011/12

Sono composti da:

Introduzione:

Comandi Unix e loro utilizzo generale

Primo esercizio dell’esame:

Guida al partizionamento, secondo quanto visto da me a lezione durante l’anno 11/12

Secondo esercizio dell’esame:

Guida allo Shell Scripting ( presa dal sito http://www.mrwebmaster.it/linux/guide/guida-shell-scripting/ e

scritta da Massimiliano Bossi)

Esempi di Esercizi

Terzo esercizio dell’esame:

Esempi di esercizi

1

Sommario COMANDI BASE ..................................................................................................................................... 3

GESTIONE DI FILE E DIRECTORY ..................................................................................................................... 3

Pwd ............................................................................................................................................................ 3

Ls ................................................................................................................................................................ 3

Cd ............................................................................................................................................................... 3

Mkdir ......................................................................................................................................................... 4

Cp ............................................................................................................................................................... 4

Mv .............................................................................................................................................................. 5

Rm e rmdir ................................................................................................................................................. 5

Touch ......................................................................................................................................................... 6

Ln ............................................................................................................................................................... 7

Chmod ....................................................................................................................................................... 7

FUNZIONI DI RICERCA .................................................................................................................................... 8

Find ............................................................................................................................................................ 8

Grep ........................................................................................................................................................... 8

GESTIONE DEL FILESYSTEM ........................................................................................................................... 9

Mount ........................................................................................................................................................ 9

Umount ...................................................................................................................................................... 9

OTTENERE INFORMAZIONI SUL SISTEMA .................................................................................................... 10

Du ............................................................................................................................................................ 10

Df ............................................................................................................................................................. 10

Free .......................................................................................................................................................... 11

Top ........................................................................................................................................................... 11

Uname ..................................................................................................................................................... 11

Lsb_release .............................................................................................................................................. 12

AMMINISTRAZIONE DEGLI UTENTI .............................................................................................................. 13

ALTRI COMANDI UTILI ................................................................................................................................. 14

Cat e less .................................................................................................................................................. 14

More ........................................................................................................................................................ 14

OTTENERE MAGGIORE AIUTO ..................................................................................................................... 15

ESERCIZIO 1 ......................................................................................................................................... 17

ESERCIZIO ESAME ........................................................................................................................................ 17

2

SVOLGIMENTO ............................................................................................................................................. 17

Creazione disco ........................................................................................................................................ 17

Partizionamento ...................................................................................................................................... 17

Creazione filesystem ................................................................................................................................ 20

Montare partizione .................................................................................................................................. 21

Smontare partizione ................................................................................................................................ 21

ESERCIZIO 2 ......................................................................................................................................... 23

GUIDA SHELL SCRIPTING.............................................................................................................................. 23

Introduzione allo shell scripting .............................................................................................................. 23

Il primo script ........................................................................................................................................... 24

Le variabili ................................................................................................................................................ 25

Altri tipi di variabili .................................................................................................................................. 27

Wildcards e altri caratteri speciali ........................................................................................................... 29

Operatori ................................................................................................................................................. 30

Istruzioni di controllo: IF .......................................................................................................................... 32

Istruzioni di controllo: CASE .................................................................................................................... 34

I cicli for e while ....................................................................................................................................... 35

Scrivere una funzione .............................................................................................................................. 36

Conclusioni .............................................................................................................................................. 38

ESERCIZI TIPICI ............................................................................................................................................. 39

ESERCIZIO 3 ......................................................................................................................................... 51

CONSIGLI ...................................................................................................................................................... 51

ESERCIZI TIPICI ............................................................................................................................................. 51

3

COMANDI BASE

GESTIONE DI FILE E DIRECTORY

Pwd

Il comando pwd serve per mostrare la directory in cui ci si trova.

La sintassi del comando è la seguente:

pwd [opzioni]

Ls

Il comando ls serve per elencare il contenuto di una directory.

La sintassi del comando è la seguente:

ls [opzione] [directory]

Alcune opzioni da utilizzare con il comando ls:

Opzione Risultato

[directory] elenca il contenuto della directory specificata, se non specificata viene considerata la directory

corrente

-a elenca anche i file nascosti

-l elenco dettagliato di file e sotto directory con i loro attributi

-R elenca ricorsivamente i file nella directory indicata e in tutte le sottodirectory

-s mostra la dimensione dei file

-S ordina i file per dimensione partendo dal più grande

-u ordina i file per data e ora di accesso partendo dal più recente

-X ordina i file per estensione e ordine alfabetico

-r elenca i file invertendone l'ordine

--color mostra i file con colori differenti

Cd

Il comando cd serve per spostarsi all'interno delle directory del filesystem.

La sintassi del comando è la seguente:

cd [directory]

Alcuni esempi di uso del comando:

cd ..

4

Serve per spostarsi alla directory superiore.

cd

Serve per spostarsi, da qualsiasi punto, alla propria directory home. È equivalente a:

cd ~

cd /etc

Serve per spostarsi nella directory /etc.

Mkdir

Il comando mkdir serve per creare directory all'interno del filesystem.

La sintassi del comando è:

mkdir [opzioni] directory

Alcuni esempi di uso del comando mkdir:

mkdir prova

Verrà creata la directory prova/ all'interno della directory corrente.

mkdir ~/prova

Verrà creata la directory prova all'interno della propria home directory, qualunque sia la

directory in cui ci si trova al momento.

mkdir -p prova1/prova2/prova3/bin

Qualora non esistessero, verranno create anche tutte le directory intermedie, a partire dalla

directory corrente.

Cp

Il comando cp serve per:

copiare un file in un altro file;

copiare un file in un'altra directory;

copiare più file in un'altra directory;

copiare directory.

La sintassi del comando è la seguente:

cp [opzioni] origine destinazione

Alcune opzioni da utilizzare con il comando cp:

Opzione Risultato

-b esegue automaticamente una copia di backup di ogni file di destinazione esistente

5

-f forza la sovrascrittura dei file, senza richiedere interventi da parte dell'utente

-i attiva la modalità interattiva, che chiede conferma prima dell'eventuale sovrascrittura di file

preesistenti

-p mantiene, se possibile, gli attributi del file

-r permette di attivare la modalità ricorsiva, consentendo la copia di directory

-v attiva la modalità "verbose", visualizza ciò che il sistema ha fatto in seguito al comando

Alcuni esempi di uso del comando cp:

cp /prova/miofile /prova1

Copia il file miofile della directory prova nella directory /prova1.

cp /prova/miofile /prova1/nuovofile

Copia il file miofile della directory /prova nella directory /prova1 dandogli il

nome nuovofile.

cp -r /prova /prova_copia

Copia la cartella /prova, e tutto il suo contenuto, nella cartella /prova_copia.

Mv

Il comando mv serve per spostare, o rinominare, file e directory.

La sintassi del comando è la seguente:

mv [opzioni] origine destinazione

Le opzioni sono le stesse del comando cp.

Alcuni esempi di uso del comando mv:

mv miofile nuovofile

Cambierà il nome al file miofile in nuovofile.

mv miofile /prova

Sposterà il file miofile nella directory /prova sovrascrivendo un eventuale file con lo

stesso nome.

mv /prova /prova_nuova

Cambierà il nome alla directory /prova in /prova_nuova.

Rm e rmdir

Il comando rm serve per cancellare file o directory dal file system.

La sintassi del comando è la seguente:

rm [opzioni] file ...

6

Alcune opzioni da utilizzare con il comando rm:

Opzione Risultato

-i chiede conferma prima di cancellare

-f forza la cancellazione del file senza chiedere conferma

-r abilita la modalità ricorsiva usata per la cancellazione delle directory

Il comando rmdir serve per cancellare directory dal file system.

La sintassi del comando è la seguente:

rmdir directory

Alcuni esempi di uso dei comandi rm e rmdir:

rm miofile

Cancella il file miofile.

rm -rf prova/

Cancella la directory prova/ e tutto il suo contenuto.

rmdir prova/

Cancella la directory prova/ solo se questa non contiene alcun file all'interno.

Touch

Il comando touch serve per aggiornare la data dell'ultimo accesso o quello dell'ultima modifica di

un file.

La sintassi del comando è la seguente:

touch [opzioni] file

Alcune opzioni da utilizzare con il comando touch:

Opzione Risultato

-a cambia solo la data dell'ultimo accesso

-c non creare il file

-m cambia solo la data dell'ultima modifica

-t

STAMP specifica la data nel formato «[[CC]YY]MMDDhhmm[.ss]»

Alcuni esempi di uso del comando:

touch miofile

7

Nel caso esista un file di nome ./miofile la data e l'ora di ultima modifica verranno

impostate a quelle correnti. In caso contrario verrà creato un nuovo file.

touch -t 0702211100 miofile

Imposta come data e ora di ultima modifica del file ./miofile alle ore 11.00 del 21

febbraio 2007.

Ln

Il comando ln serve a creare un collegamento (o link) ad un file o una directory.

Un collegamento è un file speciale che non contiene dati, ma solo un riferimento ad un altro file:

ogni operazione effettuata sul collegamento viene in realtà eseguita sul file a cui punta.

La sintassi del comando è la seguente:

ln -s /percorso_file_da_collegare/file_da_collegare

/percorso_del_collegamento/nome_del_collegamento

L'opzione -s specifica che verrà creato un collegamento simbolico.

L'uso di tale opzione è consigliato.

Chmod

Consultare la guida ai permessi dei file.

8

FUNZIONI DI RICERCA

Find

Il comando find serve per cercare all'interno di una directory e delle sue sottodirectory i file che

soddisfano i criteri stabiliti dall'utente.

La sintassi del comando è la seguente:

find [directory] [espressione]

Alcuni esempi di usi del comando:

find . -name '*.mp3'

Cerca all'interno della directory corrente ./ tutti i file con estensione .mp3.

find . -perm 664

Cerca all'interno della directory corrente tutti i file con permessi di lettura e scrittura per il

proprietario e il gruppo, ma solo di lettura per gli altri utenti.

find . -name '*.tmp' -exec rm {} \;

Cerca ed elimina tutti i file temporanei all'interno della directory corrente.

find /tmp -user pippo

Cerca tutti i file appartenenti all'utente specificato.

Grep

Consultare la relativa voce encliclopedica.

9

GESTIONE DEL FILESYSTEM

Mount

Il comando mount serve per effettuare il montaggio di un filesystem all'interno della gerarchia di

file del sistema, rendendo accessibile un filesystem a partire da una specifica directory

chiamata punto di mount (o di montaggio).

Alcuni esempi di uso del comando mount:

mount

Visualizza i dispositivi attualmente montati, il loro punto di montaggio e il tipo di filesystem

utilizzato per gestirne i dati.

mount /media/cdrom

Monta in /media/cdrom il dispositivo CD-Rom.

mount -t ntfs /dev/sda1 /media/dati_windows

Monta la partizione identificata come /dev/sda1 all'interno della

directory /media/dati_windows, in modo che tutti i dati presenti in questa partizione

diventano accessibili a partire dalla directory scelta.

Umount

Il comando umount serve per smontare un dispositivo precedentemente montato.

La sintassi del comando umount è la seguente:

umount [dispositivo]

Alcuni esempi di uso del comando umount:

umount /media/cdrom

Smonta il dispositivo CD-ROM.

10

OTTENERE INFORMAZIONI SUL SISTEMA

Du

Il comando du visualizza lo spazio occupato sul disco da file o directory.

La sintassi è la seguente:

du [opzioni] [file...]

Alcune opzioni da utilizzare con il comando du:

Opzione Risultato

-a visualizza le informazioni sia sui file che sulle directory

-s visualizza la dimensione totale complessiva

-x esclude le sottodirectory che siano parte di un'altro filesystem

Alcuni esempi di uso del comando du:

du miofile

Visualizza la quantità di spazio occupata da miofile.

du -s ~

Visualizza la quantità di spazio complessiva occupata dalla propria directory home.

Df

Il comando df visualizza a schermo lo spazio rimasto sulle partizioni e sui dischi del proprio

sistema.

La sintassi del comando è la seguente:

df [opzioni] [file...]

Alcune opzioni da utilizzare con il comando df:

Opzione Risultato

-a

include nell’elenco anche i filesystem con una dimensione di 0 blocchi, che sono di natura omessi.

Normalmente questi filesystem sono pseudo-filesystem con scopi particolari, come le voci per

l’ automounter. Filesystem di tipo «ignore» o «auto», supportati da alcuni sistemi operativi, sono

inclusi solo se quest’opzione è specificata

-h aggiunge a ciascuna dimensione un suffisso, come «M» per megabyte, «G» per gigabyte, ecc

-H ha lo stesso effetto di -h, ma usa le unità ufficiali SI (con potenze di 1000 piuttosto che di 1024,

per cui M sta per 1000000 invece di 1048576)

-t tipofs limita l’elenco a filesystem del tipo specificato

11

-x tipofs limita l’elenco a filesystem non del tipo specificato

Un esempio di uso del comando df:

df -Ht etx3

Mostra lo spazio occupato solo dai dischi con filesystem ext3, utilizzando il suffisso

specifico per l'unità di misura.

Free

Il comando free mostra informazioni sulla memoria di sistema. Molto utile se si vuole rendersi

conto della memoria disponibile sul sistema, della memoria attualmente in uso e di quella libera.

La sintassi del comando è la seguente:

free [opzioni]

Alcune opzioni da utilizzare con il comando free:

Opzione Risultato

-b mostra la quantità di memoria in byte

-k mostra la quantità di memoria in KiB (impostato di default)

-t mostra una riga contente i totali

Top

Il comando top visualizza informazioni riguardanti il proprio sistema, processi in esecuzione e

risorse di sistema, utilizzo di CPU, RAM e spazio swap utilizzato e il numero di task in esecuzione.

La sintassi del comando è la seguente:

top

Per uscire dal programma, premere il tasto «q».

Uname

Il comando uname mostra informazioni sul sistema.

La sintassi è la seguente:

uname [opzione]

Alcune opzioni da utilizzare con il comando uname:

12

Opzione Risultato

-a visualizzerà tutte le informazioni del sistema

-m mostra il tipo di macchina

-n mostra il nome host del nodo di rete della macchina

-s mostra il nome del kernel

-r mostra la release del kernel

-o mostra il nome del sistema operativo

Lsb_release

Il comando lsb_release mostra informazioni sulla distribuzione installata.

La sintassi è la seguente:

lsb_release [opzione]

Alcune opzioni da utilizzare con il comando lsb_release:

Opzione Risultato

-d mostra la descrizione della distribuzione

-c mostra il nome in codice della distribuzione

-r mostra il numero di rilascio della distribuzione

-a mostra tutte le informazioni sulla distribuzione

13

AMMINISTRAZIONE DEGLI UTENTI

adduser: il comando adduser consente di aggiungere nuovi utenti al sistema. Esempio:

sudo adduser nuovoutente

Crea un nuovo utente chiamato nuovoutente.

passwd: il comando passwd consente di cambiare o impostare la propria password o la

password di un utente. Esempio:

sudo passwd nuovoutente

Consente di impostare la password dell'utente nuovoutente. Il seguente comando invece

consente di cambiare la propria password:

passwd

14

ALTRI COMANDI UTILI

Cat e less

I comandi cat e less servono per mostrare il contenuto di un file:

cat mostra semplicemente il contenuto del file specificato;

less visualizza il contenuto di file, permette di spostarsi avanti e indietro nel testo

utilizzando i tasti freccia quando i file occupano più di una pagina di schermo. È inoltre

possibile eseguire delle ricerche nel testo digitando «/» seguito dalla parola da cercare e

premendo «Invio».

Per terminare il programma premere il tasto «q».

La sintassi del comando cat è la seguente:

cat nomefile

La sintassi del comando less è la seguente:

less nomefile

More

Il comando more viene solitamente utilizzato in abbinamento ad altri comandi. È un filtro che

permette di visualizzare l'output di un comando una schermata alla volta.

Alcuni esempi d'uso del comando more abbinato ad altri comandi:

ls | more

cat miofile | more

Il simbolo «|», solitamente chiamato pipe, serve per redirigere l'output del comando a sinistra al

comando alla sua destra.

15

OTTENERE MAGGIORE AIUTO

Per ottenere maggiore aiuto o informazioni riguardo un determinato comando, esiste il

comando man che serve per visualizzare il manuale di un determinato comando.

La sintassi del comando man è la seguente:

man [comando]

Ad esempio, per visualizzare la pagina di manuale dello stesso comando man è sufficiente digitare

il seguente comando:

man man

Una volta all'interno del manuale, per poter spostarsi al suo interno, basta utilizzare le frecce

direzionali. Per uscire dal manuale premere il tasto «q».

Quasi tutti i comandi accettano anche l'opzione -h (o --help) che fornisce una breve descrizione

sull'utilizzo del comando e delle sue opzioni.

16

17

ESERCIZIO 1

ESERCIZIO ESAME Dato un disco di 100 MB già creato e montato partizionarlo nel modo seguente:

# PARTIZIONE TIPO DIMENSIONE

1 Minix 20 MB

2 Linux 20 MB

3 Fat32 15 MB

4 Minix 15 MB

5 Linux 20 MB

SVOLGIMENTO

Creazione disco

(non richiesta all’esame)

Avviare da windows Powershell (una shell simile a quella di UNIX) e andare nella cartella di QEMU e dare il

seguente comando

qemu-img.exe create nuovo.disk 100M

Ora aprite con un editor di testo il file minix.bat e aggiungete dove c’è:

qemu-system-i386.exe -L Bios -vga std -rtc base=localtime,clock=host -hda minix.qcow ^ -no-acpi -no-hpet -no-reboot

-hdb nuovo.disk

Per ottenere:

qemu-system-i386.exe -L Bios -vga std -rtc base=localtime,clock=host -hda minix.qcow -hdb nuovo.disk ^ -no-acpi -no-hpet -no-reboot

Ora facendo partire minix il nuovo disco è montato su /dev/c0d1.

Partizionamento

Dare da minix

part /dev/c0d1

Abbiamo questo menù che mostra il disco (notare in alto a destra la dimensione 102312 KB = 100 MB):

18

Ci si sposta con le frecce e si cambia con il + e –

Per prima cosa mettiamo la dimensione ( Nell’ultima colonna)

Per la riga 3 (formata dalla partizione 4 e 5) lasciamo il rimanente (ovviamente deve essere maggiore

stretta della la somma della 4 e 5 partizione che vogliamo creare)

Assicuratevi che ci sia il valore 1 nella colonna Cyn della prima partizione, questo permette di lasciare

spazio per memorizzare la tabella delle partizioni

È importante che sia settata prima la dimensione, rispetta al tipo in modo da non avere problemi dopo (i

tipi verranno messi di default a Minix)

Ottenendo questo:

19

Ora sistemiamo i tipi (sotto la colonna Type)

Poiché possiamo farne solo 4 all’ultima diamo tipo EXTENDED ottenendo ciò:

Ora salviamo tutto premendo il tasto W

Adesso dobbiamo pensare a creare le ultime 2 partizioni dentro quella definita extended:

portiamoci su Extended e premiamo >

20

Ora rifacciamo esattamente quello che abbiamo appena fatto per le sole 2 partizioni rimanenti. Alla fine qui

otterremo:

Salviamo con W

E torniamo alla shell con q.

Ora le partizioni create saranno indicate in minix cosi:

PARTIZIONE 1 -> c0d1p0

PARTIZIONE 2 -> c0d1p1

PARTIZIONE 3 -> c0d1p2

PARTIZIONE 4 -> c0d1p3s0

PARTIZIONE 5 -> c0d1p3s1

Creazione filesystem

Da shell dare semplicemente il comando

mkfs /dev/c0d1p0

per creare il filesystem alla nostra partizione 1

Per montare (e quindi usare) la partizione è necessario prima creare il filesystem!

21

Montare partizione

(non richiesta all’esame)

Dopo aver creato una cartella /dir1 e creato il filesystem per la partizione 1

mount /dev/c0d1p0 /mnt

Smontare partizione

(non richiesta all’esame)

umount /dev/c0d1p0

Michele
Replace
Michele
Replace
/dir1
Michele
Textbox
/dir1
Michele
Line

22

23

ESERCIZIO 2

GUIDA SHELL SCRIPTING

Introduzione allo shell scripting

In questa guida affronteremo un argomento che, in Italia non trova, almeno a mio avviso, uno spazio adeguato costringendo troppo spesso gli sviluppatori interessati a rivolgersi a trattazioni in lingua inglese.

Oggetto della nostra guida sarà la pratica definita di "Shell scripting", ovvero la realizzazione di script eseguibili nella shell, pratica molto utile e diffusa nella gestione di un OS Linux.

Prima di addentrarci nei meandri della programmazione ritengo opportuno avvertire che la

presente guida si basa sulla cd. Bourne Shell, ovvero la shell standard (/bin/sh) dei sistemi Unix Like scritta da Steven R. Bourne (esistono altri tipi di shell, molte delle quali - Bash, ksh, pdksh, zsh - compatibili con questa).

L'argomento, che ha un'importanza crescente anche a seguito della grande e continua

diffusione di sistemi Linux in ambito domestico ma soprattutto in ambito lavorativo, verrà trattato partendo - come nostro solito - dalle basi al fine di consentire a chiunque abbia una minima conoscenza di Linux di affrontare l'argomento senza troppa fatica.

Partiamo quindi dalla definizione del nostro ambito di competenza, lo Shell scripting,

appunto.

Lo Shell scripting consisite nella pratica di scrittura di script (file testuali contenenti un insieme organico di istruzioni) eseguibili in ambiente Shell al fine dell'esecuzione di

compiti, più o meno complessi, sulla base della combinazione dei comandi tipici offerti dal sistema operativo.

Come abbiamo visto nella definizione di cui sopra, tali file sono caratterizzati dall'eseguibilità cioè dal fatto di avere un particolare attributo di fruizione che consiste,

appunto, nella possibilità di essere eseguito dal sistema operativo.

Vi ricordo che Linux prevede, per ogni file, tre diversi attributi che possono essere diversamente combinati:

r = lettura w = scrittura

x = esecuzione

Affinchè un file sia eseguibile all'interno della shell è necessario che gli venga assegnato il relativo permesso (+x) attraverso il comando chmod:

chmod +x nomefile

Nella prossima lezione vedremo, passo passo, come scrivere il nostro primo script.

24

Il primo script

Vediamo ora come scrivere il nostro primo script. Effetuiamo il login nella Shell ed iniziamo a lavorare...

Per prima cosa vi consiglio di creare nella Root una directory apposita dove buttare gli script (giusto per non sporcare il sistema).

Quindi (supponendo di essere già nella Root) digitiamo:

mkdir miei_script

ora, ovviamente, entriamoci dentro:

cd miei_script

Ora creiamo un file nuovo chiamato "primo.sh" (l'estensione .sh è facoltativa, ma è

sicuramente una buona abitudine utilizzarla).

Per creare il file digitiamo:

touch primo.sh

Ora apriamo il nostro file vuoto all'interno del nostro editor di testo preferito.

Supponiamo di voler usare pico:

pico primo.sh

Ora riempiamo il nostro file primo.sh con il seguente contenuto:

#!/bin/sh

#Questo è un commento e non viene interpretato

echo "Lo script funziona..."

Salviamo ed usciamo dall'editor.

Ma cosa abbiamo scritto? Semplicissimo:

alla prima riga (#!/bin/sh) abbiamo precisato che il file deve essere processato

dall'interprete sh (il percorso dovrebbe essere corretto per il 90% dei sistemi Linux, in ogni caso vi consiglio di verificare che "sh" si trovi nella directory "bin", in caso contrario correggete l'intestazione utilizzando il percorso esatto).

nella seconda riga abbiamo inserito un commento, cioè un'annotazione che non viene processata dall'interprete della shell

nella terza riga abbiamo utilizzato il comando echo che serve per stampare a video

un determinato output (nel nostro caso la frase "Lo script funziona...") che è opportuno inserire tra virgolette

Ora, come abbiamo visto nell'introduzione, settiamo i permessi del file in questo modo:

chmod +x primo.sh

Et voilà... il nostro primo script è pronto per lavorare!...

Non ci credete? Allora digitate:

./primo.sh

E state a vedere cosa succede...

25

Le variabili

Come tutti in linguaggi di programmazione anche qui particolare attenzione deve essere rivolta all'argomento variabili. Le varibili, come sappiamo, sono dei "contenitori" (porzioni di memoria) nei quali è

possibile archiviare determinate informazioni (generalmente stringhe di testo o valori numerici) che è possibile richiamare, modificare o elaborare all'interno del programma.

In fase di assegnazione ogni variabile è identificata da una denominazione univoca alla quale segue il simbolo uguale (=) che precede il valore che le viene assegnato

(attenzione: non devono esserci spazi tra il nome della variabile, l'uguale ed il valore assegnato!).

Facciamo subito un esempio riprendendo il file "primo.sh" che abbiamo visto nella passata lezione:

#!/bin/sh

MIA_VAR="Lo script funziona..."

echo ${MIA_VAR}

Nell'esempio qui sopra non abbiamo fatto altro che riprendere l'esempio della passata lezione semplicemente archiviando la frase di conferma all'interno della variabile MIA_VAR poi stampata da echo.

Avrete notato che, nella fase di assegnazione, il simbolo uguale è seguito dalla virgolette... queste, infatti, sono necessarie in quanto il valore archiviato nella variabile (nel nostro caso una frase) contiene degli spazi. Se non usassimo le virgolette la variabile MIA_VAR avrebbe come valore solamente il blocco di testo che precede il primo

spazio bianco mentre il resto verrebbe ignorato.

Ritengo opportuno segnalare da subito che qualora si volesse assegnare ad una variabile la risultatnte di un dato comando sarà necessario sostituire le virgolette con accenti gravi(backtick). Vedi esempio:

#!/bin/sh

OGGI=`date +%D`

echo "la data di oggi è "${OGGI}

Per richiamare una variabile viene utilizzato il simbolo del dollaro ($) seguito (senza spazio) dal nome della varibile stessa (preferibilmente rinchiuso tra parentesi graffa).

E' opportuno segnalare che uno degli utilizzi tipici delle variabili è quello di contenere valori passati real-time dall'utente. Per fare ciò si usa il comando read. Facciamo un

esempio:

#!/bin/sh

#Uso l'opzione -n per non nadare a capo

echo -n "Come ti chiami?"

#leggo dallo standard input il valore digitato

#dall'utente e lo assegno alla variabile TUO_NOME

read TUO_NOME

#Stampo a video il saluto personalizzato

echo "Ciao "${TUO_NOME}

26

Salvate, settate il permesso di esecuzione ed eseguite il file.

Il risultato: lo script vi porrà la domanda, voi rispondete... ed eccovi un bel saluto personalizato!

Per finire non resta che dire che il contenuto di una variabile è, per definizione, variabile... basterà, infatti, effettuare una nuova assegnazione alla stessa variabile per cambiarne il

contenuto. Qualora invece si voglia semplicemente svuotare una variabile del suo contenuto useremo:

unset MIA_VAR

che avrà come effetto, appunto, lo suotamento della variabile MIA_VAR.

27

Altri tipi di variabili

Le variabili viste fino ad ora sono dette variabili locali, sono definite dal programmatore e cessano di esistere non appena termina lo script.

Altro tipo di variabili sono le cd. variabili di Shell, variabili automaticamente inizializzate all'avvio della shell che permettono di riferirsi agli argomenti su linea di comando.

Sono detti argomenti su linea di comando quegli argomenti passati al programma tramite,

appunto, la lina di comando. Ad es.:

programma argomento1 argomento 2 ...

Ecco una tabellina riassuntiva di tali variabili:

$# numero di argomenti su linea di comando

$- opzioni fornite alla shell

$? valore di uscita dell'ultimo comando eseguito

$n Recupera il valore di uno specifico argomento su linea di comando, dove n varia tra 1 e 9. $1 corrisponde al primo argomento da sinistra

$0 il nome del programma corrente

$* tutti gli argomenti su linea di comando (es. "1 2 3 4")

$@ tutti gli argomenti su linea di comando, ogniuno quotato separatamente (es. "1" "2"

"3" "4")

$$ numero ID del processo corrente

$! numero ID del processo dell'ultimo comando messo in background

Facciamo un esempio e creiamo uno script con il seguente contenuto:

#!/bin/sh

#Uso delle variabili di Shell

echo "Numero parametri = "$#

echo "Nome del Programma = "$0

echo "Tutti i Parametri = "$*

echo "Il parmentro n.1 = "$1

echo "Il parmentro n.3 = "$3

Ora salviamo come "disney.sh", settiamo i consueti permessi e richiamiamo il nostro file

da linea di comando seguito da quattro parametri, in questo modo:

./disney.sh pippo pluto topolino paperino

L'output a video sarà:

Numero parametri = 4

Nome del Programma = disney.sh

Tutti i Parametri = pippo pluto topolino paperino

Il parmentro n.1 = pippo

Il parmentro n.3 = topolino

Per finire il nostro viaggio tra le variabili è necessario ricordarne un'altro gruppo, le cd.variabili d'ambiente caratterizzate dal fatto di conservare nel tempo il loro valore in quanto questo è pre-impostato.

28

Non ritengo opportuno soffermarmi a lungo sull'argomento per il quale mi limito a

riportarvi un semplice script di esempio che utilizza alcune tra le variabili in questione:

#!/bin/sh

#Uso delle variabili d'ambiente

echo "Informazioni sul sistema:"

echo -e "hostname: $HOSTNAME"

echo -e "hardware: $HOSTTYPE"

echo -e "OS: $OSTYPE"

echo "Informazioni sull'utente:"

echo -e "logname: $LOGNAME"

echo -e "homedir: $HOME"

echo -e "shell: $SHELL"

echo -e "path: $PATH"

Da notare che nell'esempio abbiamo utilizzato echo con l'opzione -e per abilitare l'interpretazione dei caratteri protetti con backslash.

Non mi resta che concludere ricordandovi di non settare variabili locali utilizzando denominazioni riservate alle variabili d'ambiente ed alle variabili di Shell.

29

Wildcards e altri caratteri speciali

Desidero dedicare un paragrafo di questa guida ai caratteri speciali, ovvero a quei caratteri che hanno un comportamento anomalo all'interno di uno script in quanto ad essi è assegnato, di default, una specifica funzione ulteriore alla loro semplice

rappresentazione.

Primo carattere da considerare in questa sede è l'asterisco (*) anche detto wildcards. Proviamo a digitare quanto segue:

echo *

Ci accorgeremo subito che il risultato non sarà la stampa a video del simbolo asterisco,

bensì l'elencazione sequenziale di tutti i file presenti nella directory. Perchè? Semplice,

l'asterisco (anche detto wildcards) è un carattere jolly e viene interpretato dal sistema

operativo come identificazione generica di un indeterminato numero di file.

Se avessimo scritto:

echo *.jpg

Sarebbero stati stampati a video i nomi di tutti i file .jpg della directory. Se avessimo

scritto:

echo foto_*.jpg

Sarebbero stati stampati a video i nomi di file coincidenti, ad es.: foto_mario.jpg

foto_lucia.jpg foto_mary.jpg e così via.

Ma cosa fare per stampare a video l'asterisco (senza che questo venga interpretato come wildcards)? Semplice... mettiamolo tra virgolette:

echo "*"

Altri caratteri particolari da prendere in considerazione sono le virgolette ("), il simbolo

deldollaro ($), il backslash (\) ed il backtick (`).

Tutti questi caratteri, se utilizzati senza le opportune precauzioni, verranno interpretati dal

sistema operativo...

Perchè vengano semplicemente stampati a video sarà necessario e sufficiente farli

precedere dal carattere di escape (una backslash).

Ricapitolando:

#Utilizzo errato

echo "voglio stampare: " $ \ `"

#Utilizzo corretto

echo "voglio stampare: \" \$ \\ \`"

Solo nel secondo caso i nostri simboli speciali saranno stampati a video correttamente...

30

Operatori

In questo paragrafo passiamo in rasegna i cd. operatori suddividendoli in gruppi

Operatori Matematici Si utilizzano solo ed esclusivamente con valori numerici

+ Somma

- Sottrazione

\* Moltiplicazione

/ Divisione

** Esponenzia il primo numero al secondo

% Ritorna il resto di una divisione

Per effettuare operazioni matematiche sulle variabili è necessario utilizzare

alternativamente:

il comando esterno expr tra apici gravi le doppie parentesi tonde (( e )) il costrutto let

Vediamo qualche esempio:

#!/bin/sh

#Operazioni matematiche con numeri interi

#Definiamo due variabili numeriche

X=10

Y=4

#Uso di expr tra apici gravi

R1=`expr $X - $Y`

#Uso le doppie parentesi

R2=$((X-Y))

#Uso di let

let "R3 = X - Y"

#Stampiamo a video i risultati

echo "risultato di expr: "$R1

echo "risultato delle dopie parentesi: "$R2

echo "risultato di let: "$R3

Ritengo opportuno ricordare che la funzione dei backtick, come già detto, è quella di

circoscrivere (come fanno le virgolete nel caso di variabili stringa conteneti spazi vuoti) operazioni composte da comandi seguiti da uno o più attributi tra loro separati (come nel caso di expr visto sopra).

Da ricordare che expr funziona solo con i numeri interi. Se volete lavorare con numeri decimali utilizzate il comando bc (binary calculator) in questo modo:

31

echo "2.11 + 8.7" | bc

Riprendiamo lo script matematico visto sopra ponendo che le due variabili X e Y siano

numeri decimali:

#!/bin/sh

#Operazioni matematiche con numeri decimali

X=7.3

Y=4.22

Z=`echo "$X + $Y" | bc`

echo $Z

Operatori di Confronto (Numerico) Si utilizzano solo ed esclusivamente con valori numerici

-eq Equivalenza

-ne Disuguaglianza

-gt Maggiore

-ge Maggiore o Uguale

-lt Minore

-le Minore o Uguale

Operatori di Confronto (Stringhe)

Si utilizzano solo ed esclusivamente con variabili stringa

-n Verifica che la stringa sia di lunghezza maggiore di zero

-z Verifica che la stringa abbia lunghezza zero

= Verifica che due stringhe siano uguali

!= Verifica che due stringhe siano diverse

< Verifica che la prima stringa sia lessicograficamente minore della seconda

> Verifica che la prima stringa sia lessicograficamente maggiore della seconda

Operatori Logici

! Operatore di negazione, inverte il valore logico dell'espressione al quale viene applicato. !(vero) = falso

-a Operatore AND. Ritorna vero se entrambi gli argomenti passati lo sono.

-o Operatore OR. Ritorna vero se almeno uno degli argomenti lo è.

Uno degli utilizzi tipici degli operatori (di confronto e tipici) è quello di partecipare alla

costruzione di condizioni, che assumono un particolare rilievo, come vedremo, nelle istruzioni di controllo.

E' opportuno dar menzione in questa sede che esistono altri operatori, ma ai fini di questa guida preferisco limtarmi a quelli sopra menzionati.

32

Istruzioni di controllo: IF

le istruzioni di controllo sono, come dice già il loro nome, un insieme di istruzioni che controllano (appunto) il funzionamento del programma sulla base del verificarsi o meno di date condizioni.

Per prima cosa vediamo il funzionamento del costrutto if.

Partiamo da un esempio: poniamo di voler porre una domanda e di stampare a video un messaggio a seconda che la risposta sia corretta o meno:

#!/bin/sh

#Faccio la mia domanda

echo -n "Qual'è il nome di Garibaldi? "

#Recupero la risposta

read RISPOSTA

#Stampo a video il risultato

if [ ${RISPOSTA} = "giuseppe" ]

then

echo "Risposta esatta"

else

echo "Risposta sbagliata"

fi

Il costrutto if ha una sintassi molto semplice: si esprime la condizione tra parentesi quadre

e se essa risulta vera la shell esegue le istruzioni subito dopo then. In caso contrario è

possibile specificare delle istruzioni opzionali alternative subito dopo else. Ogni costrutto if

termina con fi.

Da notare che dopo la parentesi siamo andati a capo... ma avremmo anche potuto

scrivere così:

if [ condizione ]; then

Invece di andare a capo, quindi, si aggiunge un punto e virgola alla chiusura della

parenresi quadra.

Il punto e virgola ha infatti la funzione di separatore di comandi che quindi possono essere

così mesi silla stessa riga.

Nel caso in cui ci siano condizioni multiple è possibile usare elif al posto dei vari if ed

esprimere una sola volta le istruzioni alterntative con else alla fine. Facciamo un altro esempio:

#!/bin/sh

#Faccio la mia domanda

echo -n "Quanti anni hai? "

#Recupero la risposta

read ANNI

#Stampo a video il risultato

if [ ${ANNI} -lt 10 ]

then

33

echo "Sei un bambino"

elif [ ${ANNI} -lt 18 ]

echo "Sei minorenne"

else

echo "Sei maggiorenne"

fi

Non mi resta che darvi appuntamento al prossimo paragrafo dove vedremo una valida

alternativa ad if...

34

Istruzioni di controllo: CASE

Una valida alternativa ad if è offerta dal costrutto case. Con case, nella sostanza, si costruisce una casistica di evenienze ad ognuna delle qiuali è associata una data risposta del programma.

Vediamo subito un esempio e riprendiamo il primo visto nel passato paragrafo rivisto e corretto con l'utilizzo di case:

#!/bin/sh

#Faccio la mia domanda

echo -n "Qual'è il nome di Garibaldi? "

#Recupero la risposta

read RISPOSTA

#Costruisco una casistica di risposte

case $RISPOSTA in

garibaldi)

echo "Risposta esatta"

;;

*)

echo "Risposta sbagliata"

;;

esac

Ogni istruzione case richiede - almeno - un pattern (nel nostro esempio lo è la variabile

RISPOSTA).

Successivamente vanno specificati i singoli valori possibili del pattern seguiti dal simbolo ),

dalle relative istruzioni e infine da una coppia di punto e virgola.

Il simbolo asterisco (*) esprime tutti i valori non specificati ed è opzionale.

Ogni costrutto case termina con esac.

35

I cicli for e while

Un ciclo è una ripetizione di una determinata azione per un dato numero di volte sulla base di un dato delimitatore. Per realizzare un ciclo in ambiente di shell scripting si usa for oppure while. Vediamoli

entrambi.

Il ciclo FOR crea un iterazione sulla base di una data lista di valori o di una data condizione.

Esempio di lista di valori:

#!/bin/sh

for X in 1 2 3 4 5

do

echo $X

done

In questo caso il ciclo for si ripete per ogni valore specificato (nel nostro caso verranno stampati i numeri da 1 a 5, ma avremmo potuto usare anche valori non sequenziali oppure non numerici).

Altro modo di utilizzare for è il seguente:

#!/bin/sh

for (( X=0; X<10; X++ ))

do

echo $X

done

Nell'esempio qui sopra for viene utilizzato definendo, da sinistra a destra:

valore di partenza condizione limite. Il ciclo prosegue fino a quando questa condizione risulta vera

incremento (X++ aggiunge 1 al suo precedente valore numerico)

Altro modo di creare iterazioni all'interno dei nostri script è l'utilizzo di WHILE. Grazie a while si ripetono determinate azioni fino a quando la condizione limite risulta soddisfatta.

#!/bin/sh

X=0

while [$X -le 5]

do

echo $X

X=`expr $X + 1`

done

Nel nostro caso il ciclo continerà fino a quando la condizione limite (X minore o uguale a

5) risulta vera.

36

Scrivere una funzione

Anche lo shell scripting prevede la possibilità di scrivere delle funzioni. Una funzione è una porzione di codice indipendente alla quale viene assegnata, appunto, una specifica funzione all'interno del programma.

Scrivere funzioni è molto utile quando si deve compire una determinata operazione

complessa più di una volta all'interno dello stesso programma o della stessa suite di programmi. Grazie alle funzioni si evita, infatti, di riscrivere più volte il medesimo codice operativo ma

ci si limita a richiamare la funzione alla quale è stato adibito quello specifico compito.

Una funzione può essere scritta all'interno dello script oppure su un file separato da includersi nello o negli script che usufruiranno della funzione.

Vediamo nell'esempio una semplice funzione scritta su un apposito file (separato dallo script principale) che chiameremo "miafunzione.lib":

#Attenzione!!!

#Non va messo #!/bin/sh

#Funzione per il calcolo del prezzo di una merce

#compreso di IVA.

#La funzione prevede, quale unico parametro, il

#prezzo al netto dell'iva.

tot_iva() {

IVA=`expr $1 / 100`

IVA=`expr $IVA \* 20`

TOT=`expr $1 + $IVA`

echo $TOT

}

Come abbiamo visto la sintassi è data dal nome della funzione seguita da () e da una coppia di parentesi graffe al cuni interno viene inserito il codice operativo.

Ora vediamo il contenuto dello script principale che richiama il file "miafunzione.lib" per poterne sfruttare le potenzialità:

#!/bin/sh

#Includo il file miafunzione.lib

#Nel nostro es. il file si trova nella stessa directory

. ./miafunzione.lib

#Definisco due variabili contenenti il prezzo

#netto (senza IVA) di due ipotetici prodotti

VHS=10

DVD=20

#Richiamo la funzione per calcolare il prezzo compreso IVA

echo "Prezzo di una VHS compreso Iva: `tot_iva $VHS` Euro"

echo "Prezzo di un DVD compreso Iva: `tot_iva $DVD` Euro"

37

Come risulta intuitivo non sarà necessario scrivere più volte il codice per il calcolo del

prezzo totale... basterà scriverlo una volta nella funzione e poi richiamare quest'ultima

quante volte la si necessita.

38

Conclusioni

Sulla base di quanto sin qui esposto dovreste essere già in grado di scrivere dei (più o meno) semplici script per la Shell che vi aiuteranno nella gestione del vostro OS Linux permettendovi di creare, ad esempio, comandi complessi in grado di svolgere funzioni

originariamente non previste dal sistema operativo.

Ad esempio potreste programmare uno script per la pulizia dei file di log più vecchi, oppure ancora uno script per il backup e compressione dei vostri dati, ancora uno script per automatizzare il trasfrimento via FTP di determinati file, uno script di diagnostica

dell'intero sistema, ecc.

Come avrete capito le possibilità che vi si presentano sono decisamente parecchie... Non vi resta che applicarvi e fare un piccolo sforzo di fantasia per combinare le nozioni che avete appreso in questa semplice guida con la comune conoscenza di Linux e dei sui

comandi di cui trovate (per i prncipali di questi) ampia e circostanziata documentazione sulla nostra Guida a Linux.

Con un pizzico di impegno vi accorgerete che potrete creare cosine davvero interessanti. Buon lavoro!

39

ESERCIZI TIPICI Specificare l'occupazione totale di un utente in un sistema (somma delle dimensioni dei suoi file...) #!/bin/sh if [ $# -ne 1 ]; then echo "syntax: user_size <user_name>" exit 1 fi ID="$(grep "^$1" /etc/passwd | cut -f 3 -d :)" if [ "$ID" = "" ]; then echo "User \"${1}\" not found" exit 1 fi echo "calculating..." SUM=0 for ITEM in $(find / -user "$ID" -type f | xargs du | cut -f 1); do SUM=$(expr ${SUM} + ${ITEM}) done echo "User \"${1}\" takes ${SUM} KB into the system" exit 0

Per ogni utente del sistema specificare qual è il suo file di dimensioni maggiori #!/bin/sh # Per ogni utente trovare il suo file di dimensione maggiore for UID in $(cut /etc/passwd -d : -f 3 | sort -n | uniq); do FILE=$(find / -type f -user $UID | xargs du | sort -nr | head -1) if [ "$FILE" != "" ]; then DIM=$(echo "$FILE" | cut -f 1) NOME=$(echo "$FILE" | cut -f 2) echo "UID: $UID => File: $NOME ($DIM KB)" else echo "UID: $UID => Nessun file trovato" fi done

Trovare il file più "grosso" sul sistema find / -type f | xargs du | sort -nr | head -1 find / -type f | xargs du | sort -n | tail -1

Archiviare i files più grandi di 5k e più piccoli di 100k? find / -type f -size +10 -a -size -200 | xargs tar cvf archivio.tar

40

Copiare i file da una directory all'altra senza cambiare i permessi: cp /directory/albero1/* /directory/albero2

Spostare tutti i files che iniziano per m da una directory (e sottodirectory) ad un'altra mv /directory/albero1/m* /directory/albero2

Trovare tutti i files eseguibili > 5k e evidenziando i 5 più grandi find / -type f -size +10 | xargs ls -lF | grep "\*$" | tr -s ' ' ' ' | cut -d ' ' -f 5,9 | sort -n | tail -5

Archiviare i files modificati nell'ultima settimana find / -type f -mtime -7 | xargs tar cvf archivio.tar

Trovare il processo che occcupa più memoria ram ps -axl | sort +7 -nr | head -1 | tr -s ' ' ' ' | cut -d ' ' -f 8,12

Trovare i tre files più grossi per ogni utente #!/bin/sh for UID in $(cut /etc/passwd -d : -f 3 | sort -n | uniq); do echo "Utente $UID:" find / -type f -user $UID | xargs du | sort -nr | head -3 done #/usr/bin/sh cut -f 1 -d : /etc/passwd |while read user do file=$(find / -type f -user $user |xargs du |sort -nr |head -1|cut -f 2) dimensione=$(find / -type f -user $user |xargs du |sort -nr |head -1|cut -f 1) if [ "$file" != "" ];then echo "il file " $file " di dimensione "$dimensione " e'il piu' grosso per l'utente "$user else echo "l' utente " $user "non ha file" fi

41

done

Archiviare tutti i files che contengono la parola "login" find / -type f | xargs grep -l "login" | xargs tar -cvf archivio.tar

Trovare tutti i file che includono la parola "login" ed archiviarli su di un file .txt find / -type f | xargs grep -l "login" >> list.txt

Cercare tutti i file con SUID attivato find / -type f -perm -004000 (testato)

Archiviare i files più piccoli di 100KB ma più grandi di 5KB: find / -type f -size +10 -a -size -200 | xargs ar rc archive.a Opzioni: r => sostituisci o aggiungi (nel caso un file non sia già presente) c => crea l'archivio (sopprime il noioso messaggio di notifica, non fa nulla se l'archivio esiste già) t => visualizza il contenuto (ar t archive.a)

Trovare tutti i processi per ogni utente e fornirne l'occupazione in memoria??? #!/bin/sh SUM=0 for UID in $(cat /etc/passwd | cut -d : -f 3); do for PROCSIZE in $(ps alx | tr -s ' ' ' ' | cut -d ' ' -f 4,8 | grep "^$UID" | cut -d ' ' -f 2); do SUM=$(expr $SUM + $PROCSIZE) done echo "Utente $UID : $SUM KB di processi in memoria" SUM=0 done ps alx => stampa tutti i processi in formato lungo tr -s ' ' ' ' => comprimo tutti gli spazi contigui in un solo spazio (fondamentale, altrimenti non funziona il cut)

42

cut -d ' ' -f 4,8 => estrai la 4^ e l'8^ colonna (che dopo tr sono separate da un solo spazio) che sono l'UID del proprietario e la dimensione (le ho trovate osservando il comportamento dei comandi precedenti, non c'è un manuale su come farlo!) grep "^$UID" => cerca l'UID interessato a partire dall'inizio della riga (potrebbe confondersi con la dimensione di un processo) Ricordo che le colonne ora avranno il formato "0 689" ovvero UID + spazio + SIZE cut -d ' ' -f 2=> Una volta ristretto il campo dell'utente estraggo la sola colonna dei SIZE per poi sommarli tutti

Trovare il processo con pid dispari che occupa più spazio in memoria? #!/bin/sh MAXSIZE=0 MAXPID=0 for PROC in $(ps alx | tr -s ' ' : | cut -d : -f 5,8); do PID=$(echo $PROC | cut -d : -f 1) SIZE=$(echo $PROC | cut -d : -f 2) if [ $PID % 2 -eq 1 -a $SIZE -gt $MAXSIZE ]; then MAXPID=$PID MAXSIZE=$SIZE fi done echo "Processo con PID dispari più esoso: $MAXPID con $MAXSIZE KB" Spiegazione: Dalla lista di tutti i processi comprimo tutti gli spazi contigui nel carattere ':' che userò come separatore di colonne (lo spazio faceva danno); estraggo le colonne 5 e 8 che sono PID e SIZE anche qui trovate osservando il comportamento dei comandi) Le righe ora sono della forma PID:SIZE (12:552) Estraggo i PID come prima colonna dalla variabile PROC Estraggo i SIZE come seconda colonna dalla variabile PROC Se il PID % 2 è uguale a 1 (dispari) e SIZE è maggiore di MAXSIZE Aggiorno il PID e il SIZE massimi

Calcolare la somma della dimensione di file eseguibili che hanno all'interno la parola copyright non sensitive #! /bin/sh SUM=0 for SIZEFILE in $(find / -type f | xargs grep -il "copyright" | xargs ls -lF | grep "\*$" | tr -s " " : | cut -d : -f 5); do SUM=$(expr $SUM + $SIZEFILE) done

43

echo "la somma è: $SUM" le opzioni -il del grep mi consentono di: -i per il case insensitive -l per elencare il nome del file contente la parola copyright (altrimenti mi avrebbe stampato per ogni file la riga contenente la parola copyright)

Trova il processo che occupa per ogni utente più memoria #! /bin/sh MAXSIZE=0 for USER in $(cat /etc/passwd | cut -d : -f 3 | uniq); do for PROC in $(ps -axl | tr -s " " : | cut -d : -f 4,8 | grep -v "SZ"); do UID=$(echo $PROC | cut -d : -f 1) SIZE=$(echo $PROC | cut -d : -f 2) if [ $UID -eq $USER -a $SIZE -gt $MAXSIZE ]; then MAXPROC=$PROC MAXSIZE=$SIZE fi done echo "il processo dell'utente $USER + grande è: $MAXPROC" MAXPROC="nessun processo" MAXSIZE=0 done

Copiare una directory mantenendo la struttura delle sottodirectory e i permessi, evitando però di copiare il contenuto delle cartelle(i file che all'interno che non sono directory) #/bin/sh cpdir -p /directoryA /directoryB for file in $(find /directoryB -type f); do rm $file done oppure #! /bin/sh cpdir -pr /bin /bin2 rm $(find /bin2 -type f)

44

Quali e quante estensioni ci sono nel sistema? (per estensioni si intende qualsiasi cosa ci sia dopo il carattere “.”, es: archivio.gz) La soluzione è questa: find / | rev | cut -f 1 -d '.' | grep -v / | rev | sort | uniq -c | sort -n Spiegazione: find / trova tutto (files e directories) a partire dalla root dir rev inverte ogni riga dell'output cut -f 1 -d '.' estrae il primo campo di ogni riga usando il . come separatore grep -v / eliminazione delle sole directories rev inverte di nuovo ogni riga dell'output sort ordina l'output uniq -c elimina righe duplicate contandole, ora l'output è del tipo 123 gz sort -n (non necessario) ordina i risultati numericamente Nota: Si può evitare il grep -v / usando cut -f 1 -d '.' -s. Okkio che così trovi anche tutte le cartelle e file nascosti ( del tipo .cartella o .file). Ho fatto uno script simile al tuo, escludendo cartelle e file nascosti: find / -type f -name *.* | tr -s '/' ' ' | rev | cut -d ' ' -f 1 | rev | grep -v "^\." | rev | cut -d '.' -f 1 -s | rev | sort | uniq -c find / -type f -name *.* cerco tutti i file che contengono un punto nel nome del file (i file trovati sono completi di path ad es. /root/prova/file) tr -s '/' ' ' spazi al posto di / rev stampo il nome del file al contrario cut -d ' ' -f 1 estraggo il primo campo (è il nome del file al contrario). In questo modo ho il nome del file senza path rev ristampo il nome del file "dritto" grep -v "^\." escludo tutti i file che INIZIANO con un punto (sono quelli nascosti) rev non lo ripeto più cut -d '.' -f 1 -s estraggo il primo campo. Così ho l'estensione del file rev sort ordino le estensioni in ordine alfabetico, così posso eliminare le ripetizioni con uniq uniq -c per ogni estensione ho il numero di ripetizioni

Qualcuno sa cosa significa fare la statistica dei file < 10k 100k 1000k ?????????? #! /bin/sh TOT=$(find / -type f | wc -l | tr -s ' ' : | cut -f 2 -d :) DIECIK=$(find / -type f -size -20 | wc -l | tr -s ' ' : | cut -f 2 -d :) CENTOK=$(find / -type f -size -200 | wc -l | tr -s ' ' : | cut -f 2 -d :) MILLEK=$(find / -type f -size -2000 | wc -l | tr -s ' ' : | cut -f 2 -d :)

45

CENTO=100 STAT=$(expr $DIECIK \* $CENTO) STAT1=$(expr $STAT / $TOT) STAT=$(expr $CENTOK \* $CENTO) STAT2=$(expr $STAT / $TOT) STAT=$(expr $MILLEK \* $CENTO) STAT3=$(expr $STAT / $TOT) echo "I file inferiori a 10k sono il ${STAT1}%" echo "I file inferiori a 100k sono il ${STAT2}%" echo "I file inferiori a 1000k sono il ${STAT3}%"

Per trovare ogni singolo file di testo che contiene la parola "copyright" basta fare: find / -type f | xargs grep -l "copyright" | grep "\.txt$"

Somma delle dimensione di tutti i file di solo testo (non eseguibili) che contengono al loro interno la parola copyright #!/bin/sh SOMMA=0 for VAR in $(find / -type f | xargs grep -l "copyright" | grep "\.txt$" | xargs du | cut -f 1); do SOMMA=$(expr $VAR + $SOMMA) done echo $SOMMA

per cercare un eseguibile (però è stato detto più volte) fai così find / -type f | xargs ls -lF | tr -s ' ' ' ' | cut -d ' ' -f 5,9 | grep "\*$" dove ls -F mette in fondo al nome del file alcuni simboli... mette un * se è eseguibile qunidi con tr ' ' ' ' comprimo tutti gli spazi con cut, con delimitatore lo spazio (-d ' ') selezioni i csmapi 5 e 9 (PID e SIZE) e poi estraggo le linee che hanno * alla fine (devo mette \ davanti a * per farlo interpretare bene... e il $ significa "cerca in fondo alla riga"

Trovare tutte le dir che abbiano meno di 5 sottodirs: #!/bin/sh echo "Script per stampare le dir che hanno meno di 5 sottodir";

46

for dir in $(find / -type d); do ls -F -1 $dir | grep '/' | wc -w > a.tmp if [ $(cat a.tmp) -lt 6 ]; then echo $dir; cat a.tmp; else echo ''; fi; rm a.tmp; done;

Trovare il file più grande di tipo testo che abbia un numero di righe pari sizef=0 for file in $(find / -type f -name '*.txt'); do nrrighe=$(wc -l $file | tr -d ' ' | cut -f 1 -d /) size=$(du $file | cut -f 1) if $(expr $(expr $nrrighe % 2) -eq 0 ); then if $(expr $size -gt $sizef); then sizef=$size filef=$file fi fi done echo "Il file di testo più grande con numero di righe pari è: echo $filef

Calcolare per ogni utente il numero di file modificati nell'ultimo mese for user in $(cut /etc/passwd -d : -f 3 | sort -n | uniq); do item=$(find / -type f -user $user -mtime -31 | wc -l | tr -d ' ' | cut -f 1) echo "L'utente $user ha modificato $item file nell'ultimo mese" done

Per ogni utente del sistema stampare i gruppi a cui appartiene, senza utilizzare i comandi id e groups. for x in $(cat /etc/passwd |cut -d ':' -f 1); do echo "$x: ""$(for y in $(cat /etc/group|grep -s $(cat /etc/passwd|grep -s "$x"|cut -d ':' -f 3)|cut -d ':' -f 1); do echo -n "$y ";done)";

47

done

Trovare tutti gli script del sistema, minori di 1 k, copiarli su /tmp/script/ Aggiungerli tutti i file su un file.tar ! #!/bin/sh mkdir script; FILE=$(find / type -f -size +2 | xargs grep -l "#!/bin/sh" | cp * /tmp/script);

Trovare tutti i file modificati di venerdì #!/bin/sh find / -type f |while read line do giorno=$(stat -Mtime $line |awk '{$1 print $1}') if [ "$giorno" = "Fri" ]; then ls -l $line fi done

Memorizzare in un archivio .ar tutti i file creati negli ultimi 2 giorni di dimensione minore di 5k. find / -type f -size -10 -ctime -2 |xargs ar rc filearc.ar

Calcolare per ogni utente il numero di file modificati nell'ultimo mese cut -f 1 -d : /etc/passwd |while read line do conta=$(find / -type f -mtime -30 -user $line|xargs ls -l|wc -l) echo "lo user " $line "ha modificato " $conta "file negli ultimi 30 giorni " done

Calcolare la dimensione totale di tutti i file .c #/usr/bin/sh

48

find / -type f -name *.c | while read line do conta=$(stat -size $line) tot=$(expr $conta + $tot) echo $tot > totale done

Memorizzare in un archivio .ar tutti i file creati negli ultimi 2 giorni di dimensione minore di 5k. find / -type f -size -10 -ctime -2 |xargs ar rc filearc.ar

Per ogni utente trovare i 3 file più vecchi del sistema.. #!\bin\sh USERS=$(cut -d : -f 1 | sort -f | uniq); for us in $USERS; do FILE=$(find / -type f -user $us | xargs ls -ltsT | tail -3); echo "FILE UTENTE: $us; echo $FILE; done

Calcolare il numero di righe totali che ha scritto sul filesystem un certo utente nell'ultimo mese find / -mtime -30 |while read line ; do; awk '{ if ($(ls -l $linea)) $3 == 'root' print }'; done; find / -mtime -30 |while read line ; do; ls -l $line | awk '{ print $3": "$9}' | grep ^root done;

Calcolare la somma delle dimensioni dei file *.s. #/usr/bin/sh find / -name *.s | while read line;

49

do; sum=$(ls -l $line| awk '{print $5}'); #### pippo= $(ls -l $line| awk '{sum = sum + $5} END {print sum}' ###echo $sum; tot=$(expr $sum + $tot); echo $tot > tmp; done;

Trovare tutti i file che hanno il numero di blocchi pari #/usr/bin/sh ###sum=0; find / |while read line; do; ls -l $line| awk '{if ($5%2==0) print }'; done;

Trovare i file più vecchi di un mese find / -mtime -30 |while read line ; do; awk '{ if ($(ls -l $linea)) $3 == 'root' print }'; done;

Mostrare, per ogni utente, il numero di file presenti sul sistema. find / -f |xargs wc -l -Calcolare il numero di righe totali che ha scritto sul filesystem un certo utente nell'ultimo mese

Stampare i file che finiscono per c con un numero di caratteri dispari e visualizzare la loro data #/usr/bin/sh find / -name *.c |while read line ; do; wc -c $line|awk '{if ($1%2 != 0 ) ls $2 print $2}'|xargs ls -l; done;

50

Trovare tutti i file col numero dispari di righe (quindi sono i file di testo) find / -f|while read line ; do wc -l $line| awk '{if (($1%2) !=0) print $line}' ;done;

Trovare tutti i file modificati di venerdi' (sia un venerdi' particolare che di venerdi' in generale) #/usr/bin/ksh find / -type f|while read line; do ; stat $line |awk '{if ($1 =="Mtime:" && $2 =="Fri") print "'${line}'" }' ; done;

Trovare tutti i link simbolici presenti nel sistema. find / | while read line;do if test -h $line; then echo $line ok; fi; done

Trovare tutti i file col numero dispari di righe (quindi sono i file di testo) find / -f|while read line ; do wc -l $line| awk '{if (($1%2) !=0) print $line}' ;done;

Trovare gli utenti ed i gruppi distinti proprietari dei file nelle directory /bin, /sbin, /usr/bin e /usr/sbin. Riportare i comandi utilizzati. ls -l /bin /sbin /usr/bin /usr/sbin |awk '{print $3, $4}'|sort |uniq

51

ESERCIZIO 3 Arrivato a questo punto se hai fatto bene i primi 2 hai già 24/30. Per far questo esercizio bisogna aver

capito bene come funziona il kernel minix.

Questo significa che bisogna smanettare all’interno del kernel e provare da soli

CONSIGLI Le dritte che vi posso dare sono:

provate a farlo e fate vedere al professore che sapete muovermi all’interno del kernel:

o cercate almeno di trovare il file che si deve modificare, magari anche la riga di codice (se

poi non si ha la pallida idea di cosa sostituire è cmq meglio di non aver fatto nulla)

o a volte un find e/o un grep vi può far trovare il file e la riga!

o La maggior parte delle volte i file da modificare sono nei percorsi:

/usr/src/servers/pm

/usr/src/servers/fs

ESERCIZI TIPICI Stampare "MUOIO!" ogni volta che un processo termina kprintf ("MUOIO!\n"); Nei file: /usr/src/kernel/system/do_exit.c /usr/src/kernel/system/do_kill.c nelle funzioni con il rispettivo nome [do_exit() e do_kill()] C'era una postilla ovvero di far stampare ance il PID del processo. Era un problema perchè all'interno del kernel il proc_nr non è il PID della tabella dei processi di PM ma il numero del processo della tabella del Kernel che non sono lo stesso numero quindi pescare quello giusto era comlicato e l'ora si faceva tarda... quindi il prof mi ha detto che se non lo facevo non era importante e non mi ha penalizzato. (ma questo rimanga tra me e voi...) In /usr/src/tools/ make clean (per sicurezza ripartiamo da zero) make image make hdboot (credo sostituisca anche make image, provate...) Ci sono poi due casi particolari Modifica delle librerie: prima di make hdboot inserite anche make libraries (mooolto lento) Esercizio Tasto F8 (vedi thread apposito): sempre prima di make hdboot scrivete make services Il tuo problema sai che forse è nel reboot?!

52

Prova a fare un bel shutdown e al riavvio quando sei al boot loader non fare nessuna scelta, lascia che il sistema parta dopo pochi secondi [A questo proposito me ne sono successe di tutte come a te...]

Modifica al kernel richiesta: impedire che vengano creati file il cui nome cominci con la lettera m. Intervento individuato: nei sorgenti del pm, nel file open.c c'è una funzione do_creat() Uno dei parametri sembra essere il nome. Basterebbe quindi inserire un if alla inizio della funzione che controlla il nome e se quest'ultimo comincia con m, terminare con errore. In realtà il Prof. Monga ha detto che quello non è proprio il nome del file ma una stringa che lo rappresenta (una specie di codifica interna di Minix). Ma la risposta andava bene ugualmente. Ricordo che la tua domanda è stata fatta a lezione... Il nome di un file lo si trovava passando per: /usr/src/servers/fs/open.c -> do_creat() -> common_open() -> new_node() In questa funzione nella variabile string c'è il nome del file e basta aggiungere dopo la riga: *ldirp = parse_path(path, string, opaque ? LAST_DIR : LAST_DIR_EATSYM); Il seguente pezzo di codice: code:-------------------------------------------------------------------------------- if (*string == 'M' || *string == 'm') { printf ("Niente nomi che iniziano con emme!!!\n"); return (NIL_INODE); }

Kernel: Stampare il messaggio quando un processo termina Sufficiente che la printf sia all'interno della procedura pm_exit() ovviamente nei sorgenti del PM) che viene chiamata in qualsiasi caso: syscall exit() oppure SIGKILL o SIGTERM NOTA: ho notato con un amico che qemu tende a crashare se il messaggio della exit non termina con un newline, quindi vi conviene che il messaggio sia sempre qualcosa del tipo printf("\nMESSAGGIO\n"); che per inciso produce anche un output più leggibile (per quanto possa interessare leggere "MESSAGGIO" mille volte)

Kernel: Stampare un messaggio quando un processo viene killato Modificare i seguenti file:

53

usr/src/servers/pm/forkexit.c oppure se non si conosce il file: cd /usr/src/servers/pm grep pm_exit * 1)io vado in /usr/src/servers/pm/ 2)forkexit.c 3) mi porto alla fine della funzione pm_exit() 4) metto il printf 5) vado in /usr/src/tools/ 6) eseguo i comandi make clean, make image, make hdboot 7) shutdown

Kernel: cambiare la politica di allocazione della memoria in best fit Indovinato: si deve cambiare il file /usr/src/servers/pm/alloc.c più esattamente la funzione alloc_mem dove viene usato la politica firts fit.

Kernel: Ogni volta che viene cancellato un file che inizi per 'x' stampare un messaggio inserire in /usr/src/servers/fs/link.c NELLA PROCEDURA UNLINK_FILE if (file_name[0] == 'x') printf ("File rimosso");

Kernel: scrivere un messaggio sullo schermo quando viene avviato un programma setuid root for file in $(find / -type f -name *.s); do sum=$(stat -size $file) tot=$(expr $sum + $tot) echo $tot done

54

Guida comandi Unix/Linux.comComandi sui file

ls – elenco contenuto directoryls -al – elenco formattato con file nascosticd dir – cambia directory di lavoro a dircd – cambia directory di lavoro a directory homepwd – mostra directory di lavoro correntemkdir dir – crea directory dirrm file – cancella file filerm -r dir – cancella directory dirrm -f file – forza cancellazione di filerm -rf dir – forza cancellazione directory dir *cp file1 file2 – copia da file1 a file2cp -r dir1 dir2 – copia dir1 a dir2; crea dir2 se non esistemv file1 file2 – rinomina o sposta file1 in file2se file2 è una directory esistente, sposta file1 nella directory file2ln -s file link – crea collegamento simbolico link al file filetouch file – crea o modifica filecat > file – redireziona lo standard input in filemore file – mostra il contenuto di filehead file – mostra le prime 10 linee di filetail file – mostra le ultime 10 linee di filetail -f file – mostra il contenuto di file mentre viene aggiornato iniziando dalle ultime 10 linee

Gestione processips – mostra i processi attivitop – mostra interattivamente tutti processi attivikill pid – uccide il processo con id pidkillall proc – uccide tutti i processi con nome proc *bg – elenca i job fermati o in sottofondo; ripristina un job fermato e messo in sottofondofg – porta il job più recente in primo pianofg n – porta il job n in primo piano

Permessi filechmod octal file – cambia i permessi di file a octal, numero di 3 cifre, rispettivamente per l'utente, il gruppo e tutti gli altri, somme di:

●4 – lettura (r)●2 – scrittura (w)●1 – esecuzione o visita (x)

Esempi:chmod 777 – lettura, scrittura ed esecuzione per tuttichmod 755 – rwx per il proprietario, rx per il gruppo e tutti gli altriPer ulteriori dettagli si esegua man chmod.

SSHssh user@host – connessione a host come userssh -p port user@host – connessione a host sulla porta port come userssh-copy-id user@host – aggiunge la propria chiave ad host per l'utente user per permettere un accesso pre-autenticato o senza password

Ricercagrep pattern files – cerca pattern in filesgrep -r pattern dir – cerca ricorsivamente pattern in dircommand | grep pattern – cerca pattern nel risultato dell'esecuzione di commandlocate file – trova tutte le occorrenze di file

Informazioni di sistemadate – mostra la data e l'ora correntical – mostra il calendario del mese correnteuptime – da quanto tempo la macchina in funzionew – mostra gli utenti collegatiwhoami – mostra l'utente con cui si è collegatifinger user – mostra informazioni su useruname -a – mostra le informazioni sul kernelcat /proc/cpuinfo – informazioni sulla CPUcat /proc/meminfo – informazioni sulla memoriaman command – manuale per il comando commanddf – mostra informazioni sui dischidu – informazioni sull'utilizzo dello spazio discofree – informazioni sulla memoria libera e sullo spazio di scambiowhereis app – mostra possibili locazioni di appwhich app – mostra quale app viene normalmente eseguita

Compressionetar cf file.tar files – crea un archivio tar con nome file.tar contenente filestar xf file.tar – estrai il contenuto dell'archivio file.tartar czf file.tar.gz files – crea un archivio tar compresso con Gziptar xzf file.tar.gz – estrai un archivio tar decomprimendolo prima con Gziptar cjf file.tar.bz2 – crea un archivio tar compresso con Bzip2tar xjf file.tar.bz2 – estrai un archivio tar decomprimendolo prima con Bzip2gzip file – comprime file e lo rinomina in file.gzgzip -d file.gz – decomprime file.gz in file

Reteping host – effettua un ping di host e mostra il risultatowhois domain – recupera le informazioni whois per il dominio domaindig domain – recupera le informazioni DNS per il dominio domaindig -x host – effettua un reverse lookup di hostwget file – scarica filewget -c file – prosegue un download interrotto

InstallazioneInstallazione da sorgente:./configuremakemake installdpkg -i pkg.deb – installa un pacchetto (Debian)rpm -Uvh pkg.rpm – installa un pacchetto (RPM)

ScorciatoieCtrl+C – interrompe il comando correnteCtrl+Z – ferma il comando corrente, da continuare con fg in primo piano o in sottofondo con bgCtrl+D – esci dalla sessione corrente, simile a exitCtrl+W – cancella una parola nella linea correnteCtrl+U – cancella l'intera lineaCtrl+R – cicla attraverso la lista dei comandi recenti!! - ripete l'ultimo comandoexit – esci dalla sessione corrente

* utilizzare con estrema cautela.