2009
12.09

Ciężka jest praca admina – szczególnie w okolicach godziny 17:00, gdy programiści kończą pracę i idą do domu, ale przed wyjściem wystawią jeszcze ticket treści:

Cześć,

Na serwerze developerskim działa sobie beta projektu, który na jutro musimy odpalić na produkcji. Projekt możesz zobaczyć pod adresem:

http://10.0.0.100:6666

Tak jak chciałeś, wszystko jest ładnie opisane, projekt jest w svn. Nawet, gdy zajrzysz do environment.rb to będziesz miał listę wszystkich gemów, z jakich korzysta projekt – już nie musisz się na nas wkurwiać :]

Słodko. Klienci biorą sobie do serca moje uwagi i ułatwiają mi pracę. Z uśmiechem na twarzy łączę się VPN-em do ich sieci, odpalam wskazany adres. Pięknie projekt działa. No to teraz loguję się na maszynę… mały lag – pewnie znowu ktoś u nich torrenty na noc zostawił, będę musiał wyciąć …. o jestem :)

No i nagle bęc! Ale gdzie kurka ten projekt leży? Fuck… nie napisali. Pewnie już się domyślacie o czym będzie dzisiejszy wpis – jak znaleźć katalog z projektem (current dir) mając tylko dane przekazane w tickecie.

Na wstępie kilka założeń:

  1. projekt jest odpalony w ruby (rails) przy pomocy zwykłego script/server
  2. skupimy się na dwóch systemach operacyjnych: linux oraz freebsd
  3. programiści trzymają projekty w katalogach o nazwach: dupa, kapitan_bomba, xxx, beta,

No dobrze, wiemy że projekt jest odpalony i jak sprawdziliśmy działa. Znamy przybindowany jego adres IP (10.0.0.100) oraz port TCP (6666). Te informacje to wszystko co mamy. Wiemy, że domyślny serwer railsów odpala aplikacje na porcie TCP 3000, jeśli chcemy inny adres to musimy skorzystać z parametru -p i określić numer portu TCP, który chcemy wykorzystać.

Sprawdźmy co powie nam ps:

root@mandarynka:/root# ps a | grep 6666
 9596 pts/1    S+     0:00 grep 6666
29798 pts/0    Sl+    0:04 ruby ./script/server -p 6666

Dobra mamy PID procesu (29798), więc jesteśmy w domu. Teraz jak sprawdzić katalog (current dir), gdy korzystamy z linuksa. Możliwości mamy kilka:

  • lsof
  • katalog proc
  • pwdx
  • gdb

Zacznijmy od lsof – jest to program, który zrzuca nam informacje o otwartych plikach w systemie. Gdy wywołamy ten program bez żadnych parametrów, to zostanie nam wyrzucona bardzo pokaźna (wielkość zależna od wielkości systemu) lista otwartych plików wraz z informacjami o korzystających z nich procesach. Nas jednak interesuje tylko proces o określonym pidzie – w tym wypadku 29798.

root@mandarynka:/root# lsof -p 29798 | grep -B 1 cwd
COMMAND   PID        USER   FD   TYPE   DEVICE     SIZE    NODE NAME
ruby    29798 jacek  cwd    DIR      8,1     4096 4082438 /var/apps/projekty/deszczowy_grudzien

Bingo – kto by wpadł na pomysł, że projekt będzie znajdował się w katalogu /var/apps/projekty/deszczowy_grudzien? :)

Druga opcja – katalog proc. W linuksie mamy podmontowany specjalny katalog (/proc), w którym mamy wszystkie informacje o stanie systemu, jego sprzęcie itp. Gdy wejdziemy do katalogu proc to zobaczymy wiele katalogów nazwanych liczbami oraz kilkanaście plików. Te katalogi nazwane liczbami to zmapowane do plików procesy – liczba oznacza PID procesu. W każdym takim katalogu jest plik symlink o nazwie cmd, który wskazuje na aktualny katalog. Zobaczmy jak to działa w praktyce:

root@mandarynka:/root# ls -lh /proc/29798/cwd
lrwxrwxrwx 1 jacek jacek 0 2009-12-08 22:52 /proc/29798/cwd -> /var/apps/projekty/deszczowy_grudzien

Kolejna opcja w systemach linuksowych – pwdx:

root@mandarynka:/root# pwdx 29798
29798: /var/apps/projekty/deszczowy_grudzien

No i kolejna opcja – najbardziej hardcorowa, ale cholera wie na jakiego linuksa trafimy i jakie oprogramowanie będzie tam zainstalowane. Ja wychodzę z założenia, że lepiej mieć jeden as więcej w rękawie, niż mniej :)

No to jedziemy:

root@mandarynka:/root# gdb
GNU gdb 6.8-debian
....
This GDB was configured as "x86_64-linux-gnu".
(gdb) attach 29798
Attaching to process 29798
Reading symbols from /usr/bin/ruby1.8...(no debugging symbols found)...done.
Reading symbols from /usr/lib/libruby1.8.so.1.8...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/libruby1.8.so.1.8
Reading symbols from /lib/libpthread.so.0...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
....
....
(gdb) set $buf = ""
[Switching to Thread 0x7fc3a054c6f0 (LWP 29798)]
(gdb) call (char *)getcwd($buf, 128)
$1 = 0x3a4a860 " /var/apps/projekty/deszczowy_grudzien"
(gdb) detach
Detaching from program: /usr/bin/ruby1.8, process 29798
(gdb) quit

No i pięknie. Mamy ten nasz katalog, ale w linuksie. Co jeśli mamy FreeBSD? Tam nie ma katalogu /proc, domyślnie lsof nie jest zainstalowany. Jest gdb, ale jest też prostsza metoda – narzędzie o skromnej nazwie procstat. Nie mam pod ręką żadnej freebsd z odpalonym projektem w railsach przez script/server, więc sprawdźmy sobie current dir innego procesu – powiedzmy odpalmy sobie vima:

galerianka# ps aux | grep vim
root   67884  0.0  1.5 38744  7508  p0  I+   11:08PM   0:00.08 vim

Teraz sprawdźmy jaki jest current dir tego procesu (PID = 67884)

galerianka# procstat -f 67884
galerianka# procstat -f 67884
  PID COMM               FD T V FLAGS    REF  OFFSET PRO NAME
67884 vim               cwd v d --------   -       - -   /tmp
67884 vim              root v d --------   -       - -   /
67884 vim                 0 v c rw------   9   70919 -   -
67884 vim                 1 v c rw------   9   70919 -   -
67884 vim                 2 v c rw------   9   70919 -   -

Jak widzimy w kolumnie gdzie FD = cwd mamy /tmp <- to jest właśnie nasz current dir :)

Mam nadzieję, że już nikt nie będzie musiał się zmagać z przedstawionym w powyższym wpisie problemem – a jeszcze lepiej, jak Wam klienci będą pięknie opisane tickety wystawiać – ale wtedy nie będzie takich wpisów, ponieważ jak to mówią “potrzeba matką wynalazków” ;)

PS. Oczywiście, jeśli znacie jeszcze jakieś metody zdobycia current_dir procesu to piszcie – zaktualizuje wtedy ten wpis :)

2 comments so far

Add Your Comment
  1. Dzieki za ciekawe informacje

  2. [...] źródło: blog.y3ti.pl Follow us on Twitter 26 śledzących RSS Feed 218 czytelników Jak znaleźć “current dir” procesu? 1 głosuj! Jak za pomocą ogólnodostępnych narzędzi uniksowych odnaleźć current_dir [...]