Comandi Unix poco noti

Su ogni sistema sono presenti comandi e funzioni che si rivelano spesso di particolare utilita'. Questo avviene anche su Unix che e' il sistema operativo su cui si basano gli esempi che seguono.

In realta' i comandi descritti nel seguito sono molto semplici e diffusi (anzi alcuni sono "storici") ma sono stati scelti perche' poco noti o utilizzati. La sintassi e' Solaris (l'ambiente di Sun) ma i concetti sono comuni a tutti gli Unix.


adb

adb e' l'assembler debugger. E' bellissimo (insomma dipende dai gusti). Alcuni utilizzi: mettere in debug un programma seguendolo passo passo, determinare chi ha generato un core dump, effettuare una patch su un file o un programma (utilizzandolo quindi come editor binario), ...

 

# cat pippo

00112233445566

# adb -w pippo

6?8c

6: 33445566

6?w3030

6: 0x3333 = 0x3030

6?8c

6: 00445566

^D

# cat pippo

00112200445566

 

Altri comandi utili sono $C (visualizza lo stack), $v (contenuto delle variabili), $r (stato dei registri), $z (segnali)...

Naturalmente sono disponibili altri debugger con possibilita' sempre maggiori. Ad esempio con gdb ./httpd PID si entra in debugger del processo Apache attivo con il PID e si puo' controllare con where lo stack trace oppure con gdb exec_file core_file si analizza un core dumpe e si controlla l'ultimo stack trace con bt.

Una nota a parte merita il KADB (Utilizzo del kernel debugger su sistemi Solaris).


truss

Il comando truss consente di monitorare tutte le chiamate a sistema effettute da un processo. Possono essere quindi controllate tutte le azioni che uno (o piu') processi svolgono sul sistema verificando le funzioni richiamate, i valori di ritorno ed i parametri passati.

Per ovvie ragioni di sicurezza solo root puo' seguire processi di altri utenti e vi sono particolari restrizioni nel seguire programmi cui SUID o GUID attivo.

 

# truss ls

execve("/bin/ls", 0xEFFFFE28, 0xEFFFFE30) argc = 1

open("/dev/zero", O_RDONLY) = 3

mmap(0x00000000, 8192, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0xEF

7C0000

open("/usr/lib/libw.so.1", O_RDONLY) = 4

fstat(4, 0xEFFFFAE4) = 0

mmap(0x00000000, 8192, PROT_READ|PROT_EXEC, MAP_SHARED, 4, 0) = 0xEF7B0000

mmap(0x00000000, 98304, PROT_READ|PROT_EXEC, MAP_PRIVATE, 4, 0) = 0xEF790000

munmap(0xEF798000, 57344) = 0

mmap(0xEF7A6000, 3568, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 4,

24576) = 0xEF7A6000

close(4) = 0

...OMISSIS...

lstat(".", 0xEFFFFCE8) = 0

open(".", O_RDONLY|O_NDELAY) = 3

fcntl(3, F_SETFD, 0x00000001) = 0

fstat(3, 0xEFFFFC28) = 0

getdents(3, 0x0002D110, 1048) = 1024

getdents(3, 0x0002D110, 1048) = 608

getdents(3, 0x0002D110, 1048) = 0

close(3) = 0

ioctl(1, TCGETA, 0xEFFFDF3C) = 0

bin nsr trusproxy

write(1, " b i n ".., 52) = 52

cdrom opt usr

write(1, " c d r o m ".., 46) = 46

...OMISSIS...

lseek(0, 0, SEEK_CUR) = 1706601

_exit(0)

 

Quindi all'esecuzione del comando ls avvengono le seguenti cose:

Bello vero?

Sono presenti diverse utili opzioni del comando truss quali:

-f per seguire anche i processi figli

-p PID per seguire uno specifico processo

-c per generare le statistche sull'uso delle varie system call

In Solaris 1 il comando equivalente era il trace. Comandi equivalenti su altri Unix sono strace (Linux), tusc (HP-UX), ...

 


snoop

snoop e' un semplice ma potente analizzatore di rete.

Con snoop e' possibile controllare tutti i pacchetti che passano sulla rete analizzando il livello di protocollo desiderato ed, eventualmente, filtrando opportunamente il traffico. Con snoop e' possibile catturare pacchetti, da analizzare in seguito, o generare statistiche di traffico.

In Solaris 1 il comando equivalente era etherfind. Molto diffuso (eg. Linux) sono anche tcpdump ed Ethereal


fuser

E' spesso utile sapere chi utilizza un certo file o una directory. Tale informazione e' naturalmente mantenuta nel kernel. Per ottenere questa informazione e' utilizzabile il comando fuser. Il comando e' inoltre utile quando si cerchino i processi che utilizzano file posti su una directory su cui si vuole effettuare un umount.

 

# fuser /tmp/enorme.log

/tmp/enorme.log: 4125c 3434c

# fuser -c /home4

/home4: 29075cto 14477o 14476o 14475o 14474o 26365o

 


XXstat

Alla famiglia XXstat appartengono diversi programmi che consento il controllo delle prestazioni e dell'utilizzo del sistema: vmstat, iostat, ... Tra questi e' molto utile, per controllare la ripartizione del carico su sistemi multiprocessore, il comando mpstat.

 

# mpstat 5

CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys wt idl

0 1 0 19 222 18 221 7 19 4 0 939 5 3 5 87

1 0 0 836 198 183 254 7 18 6 0 887 3 4 6 88

CPU minf mjf xcal intr ithr csw icsw migr smtx srw syscl usr sys wt idl

0 0 1 19 318 114 312 8 20 4 0 786 3 5 38 54

1 0 0 886 203 187 258 9 21 6 0 725 2 5 38 54

Una menzione particolare la merita anche netstat. Infatti il comando consente di controllare le connessioni TCP al sistema, le tabelle di routing, la statistiche di rete, ... Molto utile e' la stringa: netstat -an | grep tcp | cut -b69-80 | sort |uniq -c che riporta le connessioni TCP presenti suddivise per stato del protocollo.

 


ldd

Un programma puo' essere compilato linkando le librerie che utilizza oppure ponendo dei riferimenti a librerie dinamicamente richiamate al momento dell'esecuzione.

L'utilizzo di librerie dinamiche rende inferiore la dimensione dei programmi, consente una maggior condivisione della memoria e consente l'aggiornamento delle librerie senza la necessita' di relink dei programmi.

Tuttavia, quando un programma utilizza librerie dinamiche, e' necessario predisporre l'ambiente in modo che tutte le librerie possano essere caricate (ad esempio impostando il valore di LD_LIBRARY_PATH). Ma, a seconda della versione di Unix, del processore e delle modalita' di compilazione, sono molte le variazioni sul tema (eg. LIB, LIB_PATH, LD_PRELOAD, /lib64, ...).

Per controllare le librerie richiamate da un programma e' utilizzabile il comando ldd.

 

$ ldd ls

libw.so.1 => /usr/lib/libw.so.1

libintl.so.1 => /usr/lib/libintl.so.1

libc.so.1 => /usr/lib/libc.so.1

libdl.so.1 => /usr/lib/libdl.so.1


ps

Il comando ps consente di controllare l'elenco delle attivita' presenti sul sistema Unix: i processi. Non e' un comando poco noto! Pero' alcune caratteristiche dei processi (eg. quantita' di memoria, relazioni di parentela, ...) che il ps riporta ed alcune opzioni del comando sono molto importati e non sempre tutte conosciute.

Tra le opzioni meno note la possibilita' di personalizzare le colonne con: -o user,vsz,pid,com,rss,osz (ma anche user,pid,ppid,class,rtprio,ni,pri,psr,pcpu,stat,vsize,size,rss,pmem,comm). Ad esempio con lo script seguente si riportano, ordinati per uso di CPU i processi presenti sul sistema:

date
echo "%CPU PID PPID USER COMMAND"
ps -ea -o pcpu,pid,ppid,user,args | \
grep -v grep | grep -v pss | grep -v pcpu,pid | \
grep -v " 0.0" | \
tail +2 | sort -r | head -10 | cut -c 1-80
echo

 


shc

Scrivere programmi in shell e' un'attivita' normale per un sistemista Unix. Ma a volte utilizzare script presenta problemi: possono essere facilmente modificati ed utilizzati in contesti diversi.
C'e' un'utile comando che trasforma uno script shell in un file .c da compilare: shc. Il programma contiene lo script in forma criptata e quindi protetta.

 


ls

Finalmente un comando sconosciuto! ls e' forse la prima cosa che si impara ad utilizzare su Unix. Ma non importa, quasi qualunque cosa cerchiate, la troverete con l'ls.

La soluzione dei problemi piu' complessi e' sempre nelle cose piu' semplici.


Testo: Comandi Unix poco noti
Data: 27 Agosto 1997
Versione: 1.2.3.4.5.6.7.8
Autore: mail@meo.bogliolo.name