Unixcyclopedia - cheat și lsof

May 4th, 2008 Alex

Pentru că am cam aberat în ultimul timp numai prostii nefolositoare :) și pentru că săptămâna asta am fost liber, mă simt dator să reiau o mica serie de articole ce se concentra pe învățarea de comenzi din terminal … unixcyclopedia. Nu știu dacă folosește cuiva, dar personal mi-e atât de lene să învăț unelte de productivitate că-mi trebuie o motivație să o fac.

command line ruby cheat sheets

cheat este un utilitar în linia de comandă cu ajutorul căruia se pot afișa trucuri și sfaturi despre diverse unelte (ce au în general legătură cu Ruby1 , dar nu numai).

Pentru instalare, aveți nevoie în prealabil de Ruby și de RubyGems2. Dacă cerințele sunt respectate, instalarea se realizează cu un simplu:

  gem install cheat

Odată ce instalarea a fost efectuată, putem afla exemple de utilizare despre o grămadă de unelte.

Și sincer să fiu, articolul inițial aș fi vrut să fie despre lsof (list open files), un utilitar extrem de util ce afișează informații despre fișiere deschise de procese. Și aici vine șmecheria … un fișier în Unix poate fi un fișier fizic de pe harddisk, sau un director, sau un device hardware, sau un fișier de rețea (e.g. Internet socket, NFS sau Unix Domain socket). Practic aproape orice resursă Unix poate fi (și este în general) accesată ca un fișier.

Și aici intervine lsof:

  • vrei să afli ce procese comunică pe portul 80?
  • vrei să afli ce procese blochează un anumit fișier? sau un anumit port?
  • vrei să afli ce fișiere/porturi sunt folosite de o anumită aplicație sau de un anumit utilizator?
  • sau poate vrei să afli ce procese s-au blocat așteptând la o resursă blocată de un alt proces?

Și acestea sunt doar câteva din întrebuințările posibile … comanda este atât de cool. Și din fericire nu a trebuit să sap prin documentația man. Tot ce a trebuit să fac a fost ceva de genul …

  cheat lsof | less

Iar output-ul este ceva de genul …

  lsof -i
   -- Show all connections

  lsof -iTCP
   -- Show only TCP connections (works the same for UDP)

  lsof -i :22
   -- -i :port shows all networking related to a given port

  lsof -i@192.168.1.5
   -- To show connections to a specific host, use @host

  lsof -i@192.168.1.5:22
   -- Show connections based on the host and the port using @host:port

  lsof -i| grep LISTEN
   -- Grepping for "LISTEN" shows what ports your system is waiting for
   connections on

  lsof -i| grep ESTABLISHED
   -- Grepping for "ESTABLISHED" shows current active connections

  lsof -u ecable
   -- Show what a given user has open using -u

  lsof -c syslog-ng
   -- See what files and network connections a command is using with -c

  lsof /var/log/messages
   -- Pointing to a file shows what's interacting with that file

  lsof -p 10075
   -- The -p switch lets you see what a given process ID has open, which is good
   for learning more about unknown processes

  lsof -t -c Mail
   -- The -t option returns just a PID

  lsof -a -u ecable -i @1.1.1.1
   -- Using-a allows you to combine search terms, so the query below says, "show
   me everything running as daniel connected to 1.1.1.1" 

  kill -HUP `lsof -t -c sshd`
   -- Using the -t and -c options together you can HUP processes

  kill -9 `lsof -t -u daniel`
   -- You can also use the -t with -u to kill everything a user has open

  lsof +L1
   -- lsof +L1 shows you all open files that have a link count less than 1,
   often indicative of a cracker trying to hide something

Wow, that’s cool.

Note:

  1. Ruby este un limbaj de scripting modern, robust, orientat pe obiecte, și cu o comunitate sănătoasă
  2. RubyGems este manager de pachete din comunitatea Ruby

Posted in tips&tricks, unixcyclopedia | No Comments »

Unixcyclopedia - find

August 30th, 2007 Alex

find este una dintre cele mai utile comenzi valabile din linia de comandă, fiind unul din cele mai bune argumente împotriva folosirii managerelor de fişiere grafice (gen Windows Explorer). Cu un File Explorer grafic nu poţi spune într-un mod eficient “caută-mi toate imaginile ce au fost modificate de utilizatorul alex săptămâna trecută, fă arhivă cu ele, şi trimite-le pe mail lui gigi@gmail.com”. Combinată cu “xargs”, plus alte utilitare ce operează pe fişiere, astfel de operaţii devin de 10 ori mai uşoare şi mai uşor de automatizat.

Descriere pe scurt: caută fişiere ce corespund criteriilor date.

Problema 1: efectuează o căutare recursivă în directorul curent după numele fişierului (cu wildcards)

find . -name "*.jpg"

Rezultatul este ceva de genul …

...
./Fotografii/Vacanțe/La Mare (2007)/dsc00956.jpg
./Fotografii/Vacanțe/La Mare (2007)/dsc00957.jpg
./Fotografii/Vacanțe/La Mare (2007)/dsc00958.jpg
./Fotografii/Vacanțe/La Mare (2007)/dsc00959.jpg
...

Directorul unde se face căutarea este cel curent, denotat cu “.”, dar se poate specifica un alt director.

Problema 2: caută toate fişierele ce aparţin de un anumit utilizator.

find . -user alex

Iar rezultatul este iarăşi ceva de genul …

...
./Audio/ToConvert/Diverse/05-senses-ube.ogg
./Audio/ToConvert/Diverse/06-empathy-ube.ogg
./Audio/ToConvert/Diverse/07-reality-ube.ogg
./Audio/ToConvert/Diverse/08-sanity-ube.ogg
./Audio/ToConvert/Diverse/09-identity-ube.ogg
...

Problema 3: caută fişierele de un anumit tip

Un director este tot un fişier. Deasemenea, sub Linux/Unix, pe lângă fişierele fizice de pe hard-disk mai există şi alte tipuri de fişiere (sub Unix filozofia este … aproape orice resursă poate fi tratată ca un fişier).

Tipurile de fişiere disponibile, aşa cum apar la listing-ul comenzii “ls”, sunt …

- - fişier normal
d - director
l - link
c - fişier special (în general se găsesc în /dev)
s - socket
p - named pipe

Pentru a căuta doar anumite tipuri de fişiere (cum ar fi directoarele) cu find, putem utiliza ceva de genul:

find ~/Media/Fotografii/ -type d

Iar rezultatul …

...
/home/alex/Media/Fotografii/Evenimente/Pasti (2007)
/home/alex/Media/Fotografii/Evenimente/Nuntă Ștefan & Veronica
/home/alex/Media/Fotografii/Evenimente/Moț Ioana
/home/alex/Media/Fotografii/Evenimente/Revelion 2006
...

Problema 4: caută fişierele ce depăşesc o anumită dimensiune:

find ~/Media/Audio -size +10M

Problema 5: combinarea şi negarea condiţiilor … caută toate fişierele din directorul cu fişiere audio ce depăşesc 1 MB şi nu sunt mp3-uri :)

Argumentele pot fi combinate pentru alcătuirea unor criterii de selecţie mai specializate. Deasemenea condiţiile incluse pot fi negate dacă punem în faţa condiţiei semnul exclamării.

find ~/Media/Audio -size +10M ! -name *.mp3

Autopsii :)

Cu find poţi examina ce fişiere au fost modificate în ultimele 3 zile, sau în ultimele 30 de minute de exemplu. Poţi căuta fişiere cu un anumit set de permisiuni. Poţi deasemenea căuta fişiere ce *nu* aparţin de vreun utilizator sau grup.

Cu astfel de căutări poţi face diagnostice în cazul în care ceva nu merge bine (de exemplu în cazul în care sistemul a fost crăcuit, God forbid).
Aşadar şi prin urmare …

Problema 6: cum pot căuta fişierele ce au modificate/accesate în ultimele X zile ?

Opţiunile disponibile sunt următoarele:

-atime: când au fost fişierele ultima oară accesate
-ctime: când au fost permisiunile fişierelor ultima oară schimbate
-mtime: când au fost fişierele ultima oara schimbate

Parametrul [număr întreg] ce apare lângă aceste opţiuni specifică numărul maxim de zile de la ultima schimbare.

Astfel, pentru a afla fişierele ce au fost schimbate în ultimele 24 de ore:

find /etc -user root -mtime 1

Se pot specifica şi minute în loc de zile, folosind următorul set de instrucţiuni:

-amin: în loc de atime
-cmin: în loc de ctime
-mmin: în loc de mtime

Astfel, pentru a afla fişierele ce au fost schimbate în ultimele 30 de minute:

find /etc -user root -mmin 30

Pentru a afla fişierele ce au fost accesate în ultimele 5 minute:

find /etc -user root -amin 5

Problema 7: cum pot afla toate fişierele cu permisiuni complete de accesare?

find ~ -perm 777

Alte opţiuni utile

-nouser: arată fişierele care nu sunt asociate cu un user
-nogroup: arată fişierele care nu sunt asociate cu un grup
-links n: fişierul are N link-uri
-newer file: se găsesc fişierele modificate mai recent decât fişierul “file”

Combinarea comenzii cu xargs

Este foarte util să combini comanda find cu alte comenzi din consolă pentru a putea executa operaţii complexe pe fişiere. E util de exemplu să iei toate imaginile ce aparţin lui Alex şi au fost modificate azi şi să le muţi într-un director de backup.

Comanda find mai suportă şi opţiunea “-exec” pentru rularea unei comenzi pentru fiecare nume de fişier găsit. Însă eu prefer să mă leg de comanda xargs deoarece combinaţia este mai rapida (-exec rulează o instanţă separată a programului declarat pentru fiecare fişier găsit, şi performanţa e mult mai mică pentru un număr mare de fişiere găsite).

Despre xargs: comanda combină parametrul dat cu liniile venite din stdin şi execută comanda astfel creată.
De exemplu “echo "newDirectory" | xargs mkdir” este echivalent cu “mkdir newDirectory“.

Apare însă o problemă: numele de fişiere pot conţine newlines, iar separarea din output a fişierelor din toate exemple de până acum s-a făcut cu newline (fiecare fişier fiind tipărit pe o linie nouă). Pentru a evita astfel de erori la combinarea cu comanda “xargs” se foloseşte parametrul “-print0″ ce pune caractere NULL ca despărţitor în loc de newline … iar la comanda xargs se foloseşte parametrul “-0″ pentru a indica folosirea caracterelor NULL în stdin. Vezi exemplul următor.

Problema 8: cum pot muta toate imaginile JPG (în afară de cele ce au fost făcute “la mare”) într-un director de backup ?

find ~/Media -name *.jpg ! -iwholename *mare* -print0 | xargs -0 mv --target-directory ~/Backup

În încheiere
Desigur, comanda find este chiar complexă şi mai are parametrii posibili de care n-am discutat, deşi i-am acoperit pe cei mai importanţi. Ca de obicei, de câte ori uiţi un parametru sau vrei sa afli mai multe …

man find

Posted in shell, unix, unixcyclopedia | 4 Comments »

Unixcyclopedia - grep

August 20th, 2007 Alex

Prefaţă

Nu sunt singurul care şi-a dat seama de puterea liniei de comandă. Sunt genul de om minimalist, ce-şi bazează munca pe unelte flexibile şi evit cu dârzenie folosirea mediilor de dezvoltare monolitice :) Filozofia UNIX, unde uneltele fac un lucru, dar îl fac bine, întotdeauna m-a atras. Însă din lipsă de timp nu m-am documentat decât “pe diagonală” cu privire la uneltele din lumea UNIX, şi simt că nu-mi folosesc calculatorul la capacitate maximă.

Incep prin urmare o serie de articole mici, destinate utilizării diverselor utilitare din linia de comandă (şi nu numai) … folositoare în primul rând mie, deoarece în acest fel sunt forţat să mă documentez mult mai riguros. Şi cine ştie, poate nu sunt singurul interesat de astfel de reţete.

GREP

Probabil cel mai folosit utilitar din linia de comanda, grep este folosit pentru a căuta apariţii de texte în fişiere. Pentru filtrarea propriu-zisă se dau drept condiţii expresii regulate a căror sintaxă vine în trei versiuni: basic, extended şi perl … adică toate variantele care contează.

Problema nr 1: Cum caut în toate fişierele din directorul curent apariţia cuvântului “wordName” ?

grep -r wordName .

-r — opţiunea parcurge recursiv directorul indicat (în cazul nostru directorul curent, indicat prin “.” [punct]). Instrucţiunea este echivalentă cu …

find . -print | xargs grep wordName

Problema nr 2: Cum fac o căutare case-insensitive în toate fişierele cu extensia “*.rb” din directorul /home/alex/sampleDir ?

grep -i -r --include=*.rb wordName /home/alex/sampleDir

Opţiunea -i este pentru căutare case-insensitive. Iar opţiunea –include face căutarea doar în fişiere ce se potrivesc şablonului indicat.

Instrucţiunea este echivalentă cu …

find /home/alex/sampleDir -name *.rb -print | xargs grep wordName

Problema nr 3: cum fac să-mi afişeze contextul rezultatelor găsite la căutare ?

grep -C 1 alex /etc/passwd

Cu opţiunea -C [n] se afişează n linii de deasupra şi n linii de dedesuptul liniei ce corespunde căutării.

Problema nr 4: cum fac să-mi afişeze doar calea către fişierele ce sunt găsite la căutare ?

grep -l 'class' *.php

Comanda de mai sus poate fi combinată pentru efecte super-marfă. De exemplu putem copia toate fisierele *.php ce conţin cuvântul “class” într-un director la alegere …

grep -l 'class' *.php | xargs mv -t /target/directory

Problema nr 5: cum pot afla PID-ul proceselor Apache ?

Oops, o problemă practică şi extrem de uzuală ?

Pentru o afişare brută, este suficient ceva de genul …

ps aux | grep [a]pache

“ps” afişează lista de procese active, dar ce-i cu expresia “[a]pache” ? Simplu … dacă puneam cuvântul “apache” s-ar fi afişat în listă şi procesul comenzii enunţate.

Pentru omorârea tuturor proceselor “apache” (presupunând că s-au blocat şi nu e posibilă oprirea normală … situaţie destul de anormală) e suficientă o comandă de genul …

ps aux | grep [a]pache | awk ‘{print $1}’ | xargs kill -9

Eh … “awk” este un zeu al procesării de texte, dar vorbim altădată despre asta :)

Problema nr 6: cum pot elimina liniile nedorite (cum ar fi liniile goale) dintr-un fişier ?

cat file.txt | grep -v ^[[:space:]]*$

Opţiunea -v afişează toate liniile care nu corespund expresiei date.

Problema nr 7: cum pot afişa numele tuturor fisierelor care nu conţin un anumit cuvânt ?

Să zicem că vrem să aflăm toate fişierele *.php din directorul curent care nu conţin cuvântul “function”.

grep -L 'function' *.php

Opţiunea -L afişează toate fişierele unde nu este găsită nici o linie ce corespunde expresiei.

Concluzie

grep este o comandă pe cât de simplă, pe atât de puternică. Aş vrea să dau un ultim exemplu ce demonstrează capabilitaţile de combinare a comenzilor prin pipe-urile liniei de comandă:

ps aux | grep [a]pache | grep root | awk ‘{print “/proc/” $2 “/status”}’ | xargs cat | grep -i vm

Comanda (testată pe Debian/Ubuntu) afişează ceva e genul …

VmPeak: 23252 kB
VmSize: 23252 kB
VmLck: 0 kB
VmHWM: 6716 kB
VmRSS: 6716 kB
VmData: 3068 kB
VmStk: 88 kB
VmExe: 328 kB
VmLib: 18528 kB
VmPTE: 32 kB

Pretty cool, huh ?

Cu puţină imaginaţie e posibilă crearea unor instrumente de monitorizare a proceselor destul de avansate ;)

Posted in shell, unix, unixcyclopedia | 3 Comments »