Corso Linux Torino

From Ability
Revision as of 15:27, 10 July 2015 by 80.21.33.250 (Talk) (Created page with "== Orario e Luogo == Tutti i mercoledì 18:30-21:00 - Ufficio Poli [https://maps.google.it/maps?f=d&source=s_d&saddr=&daddr=45.064291,7.659892&hl=it&geocode=&sll=45.062382,7....")

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Orario e Luogo

Tutti i mercoledì 18:30-21:00 - Ufficio Poli Mappa

Programma

Il programma e l'ordine delle lezioni del corso potrà variare a seconda degli argomenti richiesti dai partecipanti. Di seguito una bozza del programma



Lezione 1: Overview e Comandi base

In Linux everything is a file.

Linux FileSystem -> insieme di file che genera il sistema operativo

Non ci sono estensioni, i file non si distinguono tramite il nome, ma tramite il contenuto.

Descrizione sommaria dei principali componenti del file system:

   / (root)
   /bin (binary)   
   /usr (user)
   /bin
   /sbin
   /var (variable (size))
   /home (users)
   /lib (libraries)
   /mnt (mount point (in Ubuntu spesso si trova come /media))
   /dev (devices (device drivers))
   /proc (file system virtuale, generato da OS)
   /sys (uguale a /proc, ma più settabile)
   /etc (configurazione)
   /opt (optional)
   /tmp (temporary, mount point per un fs che sta in RAM)

MOUNT POINT

Il mount point è una folder a cui si aggancia un altro file system o un dispositivo esterno.

Per esempio posso agganciare alla home l'hard disk principale: / <== HARD DISK (PARTIZIONE) - HDA1

Su /mnt posso agganciare una penna USB /mnt <== PENNINA USB

Su /home posso agganciare un hard disk di rete. /home <== hd di rete

La cosa figa è che l'apparenza è di navigare sul tuo fs, in realtà a seconda de mount point puoi utilizzare un diverso fs. In sostanza puoi usare un qualunque file come base per un fs intero.

La memoria SWAP è una quantità di memoria RAM che viene messa su disco, all'occorrenza.

Linux è multiuser e multigroup. Ogni user ha un UID, ogni gruppo ha un GID.

Permessi: sono del tipo R-W-X

I comandi sono file con permessi di esecuzione. In genere i comandi, essendo eseguibili, sono dentro /bin. Per lanciare un comando da ogni parte della shell, devi avere nel path il file in questione.

Lista di comandi

--help per avere una lista sommaria di opzioni per ogni comando:

ls

Lista dei file in una directory

Esempio output:

drwxr-xr-x  7 andrea andrea     4096 feb 19 18:44 ./
drwxr-xr-x 56 andrea andrea     4096 feb 18 15:50 ../
-rw-rw-r--  1 andrea andrea      777 feb 19 18:44 190214_corso
-rw-rw-r--  1 andrea andrea      417 feb 19 18:40 190214_corso~
-rw-------  1 andrea andrea    84179 gen 29 11:35 acabriolu.pdf
-rw-rw-r--  1 andrea andrea   489213 feb  3 20:44 aug.jpg
drwxrwxr-x 12 andrea andrea     4096 dic 16 01:38 BK_fabrizio/
-rw-r--r--  1 andrea andrea  1482528 feb 17 18:24 bk_pre_eqcheck.7z
drwxrwxr-x  2 andrea andrea     4096 feb 17 20:04 build-pre_eqcheck-Desktop-Debug/

La prima colonna indica i permessi:

drwxr-xr-x  

d sta per "directory"

rwx (111 = 7) Users
r-x (101 = 5) Groups
r-x (101 = 5) Others

Con ls -a, in genere aliasato con la, mostra pure i file nascosti.

I FILE CHE INIZIANO con . sono nascosti.

pwd

Print working directory

cd

Change directory Cambia la directory in cui ci si trova. Molto importante il cd -, che stampa la directory precedente e ci torna. cd ~ torna alla home assoluta.

man

Manuale dei comandi man con un argomento numerico mostra diversi tipi di manuale.

Questo comando è una man dal cielo.

cat

Visualizza l'interno di un file (codificato in ASCII)

grep

Pattern matching File README con questo contenuto: Andrea Cabriolu Andrea Sanna Paolo Doz

Ex.

grep "Andrea" README

Stampa solo le righe che matchano Andrea

Pipe |

Utilizza come input l'output di un comando

Ex.

cat README | grep Andrea 

Stai passando l'output del cat al grep

touch

Crea un file

  • less

Stampa un file a pagine Ex.

dmesg | less

Passi a less una sfilza di messaggi, e lo stampa a pagine

ps

Mostra i processi attivi. Il vantaggio di ps rispetto a top è che posso usare grep. ps aux mostra tutti i processi, anche quelli non forkati dalla shell.

kill

Uccide un processo L'opzione -9 uccide di sicuro il processo. Il "-9" è un segnale indirizzato all'uccisione del processo. Processo in foreground -> ha il controllo dell'attività Processo in background -> non ha il controllo dell'attività, ma è attivo

tac

cat al contrario

sort

ordina

du

stima il disk usage

chown

cambia l'owner del file

chown utente:gruppo file

es.

chown root:www-data file
chmod

Cambia i permessi di un file Us. chmod utenti(+-)permessi file Ex. chmod o-r README -> toglie i permessi di lettura agli altri utenti

cp

Copia un file in un'altra dir

mv

Sposta un file in un'altra dir

mkdir

Crea una directory mkdir -p -> permette di creare una cartella con già le sottodirectory

tree

Cisualizza l'alberazione delle cartelle come un tree

ln

Crea un link

Es.

ln -s file pippo

Crea un link simbolico Se crei un sl pippo -> file, poi cancelli file, il link è sospeso, ma esiste. Se ricrei il file, il link torna a funzionare. L'hard link è diverso. Se crei un hl pippo -> file, poi cancelli file, il link non è sospeso, ma punta al file, se l'è copiato. Quel file sarà rimosso dal sistema quando cancelli l'hard link.

  • IN UN SISTEMA LINUX UN FILE È RIMOSSO QUANDO TUTTI I RIFERIMENTI AL FILE SONO CANCELLATI.
>

Redirige l'output di un comando, sovrascrivendo

>>

Redirige l'output di un comando, appendendo

echo

Stampa sullo stdout

  • wc -> word counter, conta le parole

Conta le righe:

wc -l 

Conta il numero di file in una dir:

ls | wc


`

Apice inverso, stampa l'output del comando. Trasforma l'output di un comandi in stringa

es.

STRINGA=`ls`

Il comando `` può essere sostituito da $(comando)

es

STRINGA=$(ls)
tar

Manipola un archivio di file

Creo un archivio:

tar cf archivio.tar 

Estraggo un archivio:

tar xf archivio.tar.gz2 

Crea un archivio nominato con la data attuale (con j comprimi con bz2):

tar jcvf archivio_$(date +%Y%m%d).tar.bz2
file

Identifica il tipo di file

whoami

Mostra il nome dell'utente che attualmente sta usando la console.

export

Salva una variabile

Ex: aggiungi /home/andrea alla variabile $PATH

export PATH=$PATH:/home/andrea
history

Sstampa tutti gli ultimi comandi lanciati Lo shortcut da tastiera è CTRL-R

which

Indica dove si trova il file, se sta nel PATH

free

Mostra la memoria libera

mount

Monta una partizione

Mostra dove sono montate le partizioni:

$ mount

/dev/sda1 on / type ext4 (rw,errors=remount-ro)
proc on /proc type proc (rw,noexec,nosuid,nodev)

Si legge:

  • /dev/sda1 è montato su /, il fs è di tipo ext4
  • proc è montato su /proc, di tipo proc

SI PUÒ MONTARE UN DEVICE IN DUE POSTI

dmesg

Stampa i messaggi dal kernel



Lezione 2: Comandi avanzati e bash scripting

cut

split di una stringa

cat /etc/passwd | cut -d: -f1

divide la stringa in base a ":" e prende il primo campo.


tr

elimina dei caratteri all'interno della stringa

cat /etc/passwd | tr -d [a-z]

elimina le lettere dalla "a" alla "z"


ssh

permette di accede ad un server in ssh

ssh root@bool.abinsula.com

Usare un server pubblico per accedere ad una macchina dietro NAT

dal pc dietro NAT

ssh -R 1208:0:22 root@boole.abinsula.com

dall'esterno

ssh root@boole.abinsula.com -p 1208

awk

shell simile a bash, utile per il passaggio di file di testi


wget

scarica pagina http, https, ftp


curl

simile a wget


netstat

netstat -autwp
netstat -putan

danno informazioni sui socket aperti


sed

sostituisce dei caratteri o stringhe interne all'interno di una stringa. "s/" o "s#" è il carattere di inizio stringa da modificare mentre "/g" o "#g" è il carattere di fine stringa da modificare

echo "Ciao Andrea" | sed s/Andrea/Paolo/g

-->

Ciao Paolo
echo "Ciao An\drea" | sed s#A\ndrea#Paolo#g

-->

Ciao Paolo
echo "Ciao 079andrea079" | sed s#[0-9]#A#g

-->

Ciao AAAandreaAAA


dd

copia byte a byte


diff&patch

diff trova le differenze tra due file

file1.txt

ciao
mi chiamo
Paola

file2.txt

ciao
mi chiamo
Francesca
diff file1.txt file2.txt

-->

3c3
< Paola
---
> Francesca

trova le differenze tra i due file (al posto di "Paola" metti "Francesca" nella terza riga)

diff -rup file1.txt file2.txt > file.patch

-->

--- file1.txt	2014-03-04 20:30:38.008641205 +0100
+++ file2.txt	2014-03-04 20:29:06.808640126 +0100
@@ -1,3 +1,3 @@
 ciao
 mi chiamo
-Paola
+Francesca

crea il file di patch per passare da file1.txt a file2.txt

patch file1.txt file.patch

applica la patch al file1.txt per trasformarlo nel file2.txt


mknod

Il chip può avere molte funzionalità, attraverso il driver si riesce a dargli la funzionalità desiderata I device driver possono essere:

  1. a caratteri --> comunichi col driver passando dei caratteri (non puoi mai tornare indietro, seriale)
  2. a blocchi --> accede blocchi di porzioni (dischi, usb, mmc)
  3. di rete --> interfacce speciali come ad esempio wlan0, eth0, can0 etc.etc (queste interfacce non sono create tramite il comando mknod)

I nodi sono file speciali che permettono di accedere al device driver e sono caratterizzati da due numeri:

  1. major --> tipo di driver
  2. minor --> istanza del device
sudo mknod pippopaperino b 8 17

creo il device pippopaperino di tipo a blocchi (b) con major number 8 (tipo sd)

sudo mount pippopaperino /mnt

Monto il device pippopaperino nella cartella /mnt

less /proc/devices

ti permette di vedere i driver abilitati nel sistema, riportando il major number

sort

ordina una lista lista.txt

vvv
fff
aaa
ddd
lll
ccc
vvv
cat lista.txt | sort

-->

aaa
ccc
ddd
fff
lll
vvv
vvv


uniq

cancella due righe consecutive uguali

cat lista.txt | sort | uniq

-->

aaa
ccc
ddd
fff
lll
vvv


01_script.sh

#!/bin/bash

IP=$(ifconfig eth0 | grep inet | grep -v inet6 | cut -d':' -f2 | tr -d [a-zA-Z])
echo "Ciao il mio IP e' $IP"


02_script.sh

#!/bin/bash

IP=$(ifconfig $1 | grep inet | grep -v inet6 | cut -d':' -f2 | tr -d [a-zA-Z])
echo "Ciao il mio IP e' $IP"


03_script.sh

#!/bin/bash

for ((x=0;x<10;x++)); do
	echo "Numero: $x"
done


04_script.sh

#!/bin/bash

for x in 0 1 2 3 4 5 6 7 8 9; do
	echo "Numero: $x"
done


05_script.sh

#!/bin/bash

for x in $(seq 0 10 1); do
	echo "Numero: $x"
done


06_script.sh

#!/bin/bash

for x in $(cat dipendenti.txt); do
	echo "$x sei licenziato"
done


07_script.sh

#!/bin/bash

echo "Quanti anni hai?"
read eta 

if [ $eta -gt 18 ]; then
	echo "Sei maggiorenne!";
else
	echo "Sei minorenne!";
fi


08_script.sh

#!/bin/bash

if [ -f dipendenti.txt ]; then
	for dipendente in $(cat dipendenti.txt); do
	echo "$dipendente e' licenziato";
	done
else
	echo "Non dipendenti"
fi


09_rubrica.sh

#!/bin/bash

FILE="/home/paola/Documenti/Corso/AbinsulaLinux/Lezione/elenco_telefonico.txt"

function inserisci() {
	echo "nome"
	read NOME
	echo "cognome"
	read COGNOME
	echo "telefono"
	read TELEFONO
	echo "$NOME:$COGNOME:$TELEFONO" > $FILE

	clear

	echo "Contatto inserito:"
	echo "$NOME:$COGNOME:$TELEFONO"
}


function cerca_nome() {
	echo "nome"
	read NOME_UTENTE
	NOME=$(cat $FILE | grep $NOME_UTENTE | cut -d: -f1)
	COGNOME=$(cat $FILE | grep $NOME_UTENTE | cut -d: -f2)
	TELEFONO=$(cat $FILE | grep $NOME_UTENTE | cut -d: -f3)

	clear	

	echo "Contatto:"
	echo "$NOME:$COGNOME:$TELEFONO"
}


function cancella() {
	echo "nome"
	read NOME_UTENTE
	NUOVO_FILE=$(mktemp)
	cat $FILE | grep -v $NOME_UTENTE > $NUOVO_FILE
	mv $NUOVO_FILE $FILE

	clear

	echo "Contatto eliminato!"
}


echo "Menu"
echo "1 - Inserisci"
echo "2 - Cerca per nome"
echo "3 - Cancella"


read SCELTA

if [ $SCELTA = "1" ]; then
	inserisci
fi

if [ $SCELTA = "2" ]; then
        cerca_nome
fi

if [ $SCELTA = "3" ]; then
        cancella
fi


10_email.sh

#!/bin/bash

NOME="Paola"
BOSS="Andrea Sanna"
DATA=$(date | cut -d, -f1)


cat > email_licenziamento.txt << CABRIOULU


Ciao $NOME,
ti comunico che oggi $DATA tu sei licenziato,

In fede,

$BOSS

CABRIOULU

Lo script crea un file email_licenziamento.txt tramite il comando cat. Il comando di "creazione file" termina quando su una linea singola si trova la parola CABRIOULU

11_export_variabili.sh

#!/bin/bash

export CC="peppa"
export LD="pig"
source variabili.sh

Lo script esporta 2 variabili. Per renderle disponibili nella shell e quindi utilizzabili si usa il comando source

Lezione 3: Linux boot, dal poweron alla shell

Slide http://users.abinsula.com/~paolodoz/linux_day_2013/Fastboot.pdf versione ppt in macchina virtuale che si riavvia di continuo

Nessuno ha preso appunti?



Lezione 4: GIT

- Visualizzare il branch direttamente nella PS1

 Aggiungere questo al .bashrc
 parse_git_branch() {
   git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ \[\1\]/'
 }
 PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\[\033[00;32m\]$(parse_git_branch)\[\033[00m\] \$ '


- Che cosa è un version control system e quali sono i più famosi (svn, git)?

- Cosa è Git?

- Come si crea un repo sul proprio pc (git init)?

- Cosa è un commit (git commit e git add)

- Cosa sono i branch (git branch)?

- Come ci si sposta tra commit (git checkout)

- Come si analizzano le modifiche (git diff e git status)

- Cosa sono i repo origin e come si usano? (git push e git pull)

- Come si scarica un repository (git clone)

- Come si aggiorna la working copy (git fetch)

- Tecniche di merge (git merge, git rebase, git cherrypick)

- Come si prende la versione per un rilascio (git describe)

- Come si risolvono errori comuni (git clean, git revert, git reset, git checkout)

- Come si trova un bug (git bisect)

- Cosa sono i tag (git tag)

- Come si ignorano alcuni file (gitignore and keepdirectory)

Advanced

- Cosa sono i submodule e come si usano (git submodule, init, update, sync, summary)

- Cosa sono gli stash (git stash save, pop, apply, drop)

- Come si recupera un commit perso (git reflog)

- vedere un repository git via http (git instaweb --httpd=webrick)

- Git "grafico" (gitg, gitk)



Lezione 5: Kernel

Come configurare, compilare e avviare un nuovo kernel. Spiegazione delle principali sezioni

Changes sulle new releases: http://kernelnewbies.org/Linux_3.14

Link ufficiale: http://wiki.ubuntu-it.org/AmministrazioneSistema/CompilazioneKernel

  • Modulo -> porzione di codice caricata dinamicamente sul kernel
  • Driver -> porzione di codice caricata staticamente sul kernel

Due modi per inserire i moduli:

  • Insmod -> non controlla le dipendenze
  • Modprobe -> le controlla



git://git.freescale.com/imx/linux-2.6-imx.git

kernel da scaricare


make menuconfig

configurare il kernel (lanciare il comando dalla root del kernel scaricato)


ncurses dev

possibili pacchetti da scaricare per visualizzare il menù di configurazione del kernel


*

driver build-in (compilati all'interno del kernel)


M

moduli (compilati successivamente e solo se vogliamo compilare anche i moduli)


insmod <filename.ko>

inserisce il modulo per il kernel, ma non controlla eventuali dipendenze


modprobe <filename.ko>

inserisce il modulo e eventuali altri moduli che sono dipendenze di quest'ultimo. Le dipendenze vengono impostate in fase di compilazione


shift + 7

cerca all'interno del menù di configurazione


shift + ?

help


VOCI PRINCIPALI

ogni voce identifica una sezione del kernel

  • General Setup
tipo di compressione
supporto swap
utilizzo system D	-->	abilitare code POSIX
dimensione kernel log buffer size
control group support	-->	System D
ramdisk	-->	mount point, compressione
optmize for size
embedded system	-->	sempre abilitato nei sistemi embedded, apre nuovi menu
kernel performance events and counters
GCOV-based kernel profiling	-->	coverage - per capire con i test quanta porzioni di codice è stata utilizzata
  • Enable Loadble Module Support
  • Devices Driver
  • Debugfs
interfaccia che mette a disposizione file e opzioni per debugare
  • Firmware Devices
impostazioni del firmware
  • File System
  • Kernel Hacking
  • Security Options
  • Virtualization


DOMANDE

Tutti i driver possono essere compilati come moduli?

Sì, solo se al loro interno hanno init module ed exit module


STEP

  1. Salvare la configurazione effettuata (salvataggio nel file .config)
  2. Spostare il file .config in /arch/x86/configs
  3. make nomefile_defconfig (oppure make oldconfig)
  4. make -j 6 zImage
  5. make -j 6 modules
  6. make -j 6 modules_install
  7. sudo make install
  8. sudo grub update



STEP V2 =)


  • Vedere il kernel attualmente in uso (e.g. Linux moody-xps13 3.11.0-15-generic #25-Ubuntu SMP Thu Jan 30 17:22:01 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux)
 $uname -a



  • Estrarre l'archivio
 $tar -zxvf linux-3.11.1.tar.gz


  • Sotto /linux-3.11.1$ ll arch/x86/configs/ ho tre possibili file di configurazione
 $ls /linux-3.11.1$ ll arch/x86/configs/
   -rw-r--r--  1 moody moody 7293 set 14  2013 i386_defconfig
   -rw-r--r--  1 moody moody  539 set 14  2013 kvm_guest.config
   -rw-r--r--  1 moody moody 7284 set 14  2013   (*) più simile al mio 


  • Scelto il file di configurazione lancio il make
 $make x86_64_defconfig

Questo comando non fa altro che copiare il file x86_64_defconfig sotto .config quindi è equivalente a:

 $cp arch/x86/configs/x86_64_defconfig .config

In teoria dovrei poi editare questo file per configurare il kernel da zero, in pratica è troppo complicato. Quindi uso il file di configurazione attualmente in uso dal mio kernel

 $cp /boot/config-3.11.0-15-generic .config


  • Aggiungo/tolgo le cose che mi servono dal mio file .config usando il menu di configurazione (potrei anche editarlo a mano)
 $make menuconfig


  • $make -j6 bzImage


  • $make -j6 modules


  • #make -j6 modules_install


  • #make install


  • #update-grub

FILE IMPORTANTI

  • linux/drivers/input
kconfig
Makefile
MAINTAINERS
  • linux
Documentation
Makefile


COMANDI IMPORTANTI

cat /proc/cmdline

conoscere kernel usato


/boot/config-3-11-0-17-generic

file di configurazione del kernerl usato


lspci

conoscere hw


lsusb

conoscere hw


ls /lib/modules

elenco kernel


uname -a

kernel che gira in questo momento


cd /lib/modules/3.17-generic/kernel

E' la cartella dove si trovano i moduli del kernel con nome 3.17-generic. Per entrare nella cartella di quello che gira attualmente sul sistema, si può integrare il comando precedente in questo modo

cd /lib/modules/`uname -r`/kernel

Lezione 6: Yocto e Cross-compilazione

La cross-compilazione serve a creare un binario che deve girare su un'architettura diversa da quella della macchina su cui si è lanciata la cross-compilazione.

La toolchain è l'insieme delle librerie (già cross-compilate) da cross-compilare insieme al codice. Chain perchè l'output di uno dei tool è l'input del successivo.

Yocto è uno strumento che genera toolchain.

Yocto è una meta-distribuzione, da configurare per girare su un particolare hardware. Di base è un file di testo, a cui dare in pasto una recipe (ricetta), un'insieme di istruzioni ed elementi che permettono la customizzazione di Yocto.

Recipe -> contiene diverse info. Prima di tutto come avverrà la compilazione, poi le dipendenze, etc.

Esempio: devo compilare gstreamer, ma solo 3 pacchetti su 50. Quindi la recipe di gstreamer permette di dividere il compilato in pacchetti diversi, e poi caricare solo quelli che ti servono.

C'è una ricetta speciale, "image", che dice quali pacchetti vuoi, e alla fine genera la core_image.

Sopra le ricette ci sono i layer, chiamati meta. Raccolgono insiemi di ricette. Per esempio, meta-ability contiene le ricette per i pacchetti relativi solo ad Ability. Lo scopo finale è quello di raggruppare il lavoro, in qualche modo. Ottenuto un set di ricette interessante, si può radunare in un meta e clonare.

C'è molto lavoro svolto su Yocto, per esempio se ti serve un meta per KDE, puoi rintracciarlo e scaricarlo.

Le ricette hanno estensione ".bb" (bitbake). Il template del nome è "PN_PV.bb". E' una convenzione. PackageName, PackageVersion. Quindi una ricetta si può chiamare telemaco_3.0.bb.

Scriptando un po', si possono creare ricette astrattissime.

Ogni ricetta può essere chiamata per:

- essere compilata - essere inclusa come pacchetto

Passi durante la compilazione:

do_fetch do_unpack do_configure do_compile do_install do_packages do_somethingelse

Il processo di cross-compilazione

Automatizzare una build (Ability)

Remote debugging

  • gdb
  • gdbserver

compito finale

Realizzare una build yocto per replicare il filesystem della demo TATA

Esercizi

ES 1: Connessione automatica ssh

Realizzare un script per la connessione automatica ssh verso un host che espone un servizio su una porta specifica

INPUT:

  • username connessione ssh
  • porta da cercare
  • interfaccia di rete su cui effettuare lo scan

OUTPUT:

  • stampa a video degli IP che hanno il servizio cercato attivo
  • avvio automatico di connessione ssh verso il primo host che espone quel servizio

BONUS:

  • lettura dei parametri in ordine casuale tramite -p -u
  • se non specificati parametri default

Esempio pratico di utilizzo: Voglio connettermi al device Simpleaudio ma ad ogni avvio prende un IP diverso, espone il servizio sulla porta 50003

Programmi da usare

  • ifconfig/ip
  • nmap (attenzione al range su cui viene lanciato lo scan)
  • grep
  • tr/sed

Nota bene: lo stesso servizio può essere in esecuzione sulla macchina locale e l'ip deve escluso dalla lista di connessione

ES 2: Ricompilazione kernel per il proprio pc

Obiettivo dell'esercitazione è ricompilare e installare l'ultimo kernel disponibile su https://www.kernel.org/ (3.14 ad oggi) per il proprio notebook.

Prestare particolare attenzione alla configurazione cercando di eliminare il supporto per i device non utilizzati e scegliere di quelli disponibili, quali includere come moduli e quali built-in.

Consegna 16 aprile

Se per la compilazione/installazione vi manca qualche pacchetto, riportatelo nel capitolo kernel qui sopra

Risorse

  • The Linux command line [1]
  • The bash manual [2]
  • Bash reference card [3]