![]() |
| By Vishnu Ram V Uvod Ponekad se sistem administratori nadju u situaciji gde standardni način rešavanja problema ne donosi rezultate. Standardni načini su test skriptovi, gledanje log (dnevnik) fajlova, promena konfiguracije i slično. U ovim slučajevima potrebno je zaći duboko u unutrašnje stvari servera. Strace se pokazao kao koristan program u ovim situacijama. Strace preseca i beleži pozive (koje prave procesi sistema) i signale (koje procesi primaju). Ova strana pokazuje kako da koristiš "strace" pri rešavanju Apache problema iz stvarnosti. Opisaću problem i početni pokušaj da se ispravi. Opisaću kako Apache radi pre nego što pogledam "strace" rezultate. Ostale opcije "strace" su previše za ovaj članak tako da pogledaj "man" (priručne) stranice. Opis problema Problem: Ne mogućnost slanja mejla (pošte) sa web strane koristeći PHP 'mail()' funkciju. OS: RedHat SMTP Server: Sendmail Web Server: Apache/1.3.22 - virtuelno okruženje, server ima više sajtova. PHP verzija: 4.0.6 Početni pokušaj rešavanja problema Hajde prvo da simuliramo problem i vidimo greške. Napraviću test skript, mail.php, koji koristi mail() funkciju za slanje pošte.
<?php
error_reporting(E_ALL); $to = "Vishnu $subject = "This is a test email"; $message = "This is a test email, please ignore."; if (mail($to,$subject,$message)) { echo "Thank you for sending email"; } else { echo "Can't send email"; } ?> Skript mail.php ide u web sekciju virtuelnog sajta, i pristupa mu se preko programa za gledanje veba (browser). Rezultujuća strana pokazuje "Can't send email", nema poruke o PHP grešci. Poštin log/dnevnik ne pokazuje tragove da je pošta poslata iz virtuelnog sajta. Treba da provalim da li je problem specifičan za virtuelni sistem ili je problem celog servera. Isti skript je korišćen u više virtuelnih sistema i uvek isti ishod. Znači problem nije u virtuelnom sistemu, nego je problem celog sistema. Izgleda da je veza Apache/PHP raskinuta. Pogledaću da li je mail() funkcija onemogućena u php.ini fajlu korišćenjem "disable_functions". [root@dns1 root]# grep disable_functions /etc/php.ini disable_functions =Ne, mail funkcija nije onemogućena. Ja sam omogućio display_errors i display_startup_errors u php.ini tako da sve unutrašnje PHP greške se pokazuju na web strani, ali i ovo nije pomoglo. Test PHP strana ne pokazuje bilo koju grešku i nema poruka o greškama u Apache, Sendmail ili drugim dnevnicima. Šta je sledeće? [ Kada ispravljaš greške na sistemu koji je u stvarnom proizvodnom okruženje, onda je bolje da prvo probaš na test sistemu, koji treba da je isti kao i proizvodni. Ako ovo nije moguće, obrati pažnju da se greške ne pokazuju u brouseru i pošalji ih u dnevnike/log fajlove. Ovo je mnogo sigurnije i korisnici se ne dosadjuju porukama koje ne razumeju. -- René ] Kao što sam napomenuo ranije, "strace" je veoma koristan u otkrivanju šta se dešava na nivou procesa. Pre upotrebe strace programa, daću kratko objašnjenje kako Apache posluje sa dolazećim zahtevima. Izlet u Apache Apache se pokreće kreiranjem roditeljskog procesa sa root privilegijama. Ovo je glavni proces, i odgovoran je za kreiranje i račvanje dece procesa i njihovo održavanje. Glavni proces ne služi ni jedan zahtev, deca procesi služe i udovoljavaju zahtevima. Broj besposlenih dečijih procesa u svakom vremenu je određen direktivama "MinSpareServers" i "MaxSpareServers" u httpd.conf fajlu. Kada novi zahtev dođe, preuzima ga i služi jedan od besposlenih dečijih procesa. Ako nema besposlenih procesa, roditeljski proces napravi novi. Gledajući rezultat "ps" komande, jasno je da je roditeljski proces broj PID 1861. Radi sa "root" privilegijama dok svi dečiji procesi rade kao korisnik "apache". [root@haqmail ~]# ps aux | grep httpd USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1861 0.0 0.4 25680 1992 ? Ss Sep24 0:02 /usr/sbin/httpd apache 2295 0.0 0.4 25852 2024 ? S Sep24 0:00 /usr/sbin/httpd apache 2296 0.0 0.4 25852 2024 ? S Sep24 0:00 /usr/sbin/httpd apache 2297 0.0 0.4 25852 2024 ? S Sep24 0:00 /usr/sbin/httpd apache 2298 0.0 0.4 25852 2024 ? S Sep24 0:00 /usr/sbin/httpd apache 2299 0.0 0.4 25852 2024 ? S Sep24 0:00 /usr/sbin/httpd apache 2300 0.0 0.4 25852 2024 ? S Sep24 0:00 /usr/sbin/httpd apache 2301 0.0 0.4 25852 2024 ? S Sep24 0:00 /usr/sbin/httpd apache 2302 0.0 0.4 25852 2024 ? S Sep24 0:00 /usr/sbin/httpdKomanda "pstree" daje pregledniji izgled veze između procesa roditelja i dece.
[root@haqmail ~]# pstree -p | grep httpd
+-httpd(1861)---httpd(2295)
| +-httpd(2296)
| +-httpd(2297)
| +-httpd(2298)
| +-httpd(2299)
| +-httpd(2300)
| +-httpd(2301)
| +-httpd(2302)
Using strace
Sada znamo da je naš zahtev za mail.php služen od strane Apache dečijeg procesa i da "strace" može pomoći u nalaženju detalja šta se dešavalo, ali tu je još jedan problem: koji dečiji proces je služio mail.php zahtev? Treba da znamo tačan identifikacioni broj dečijeg procesa ili tragamo za svim dečijim procesima i onda sortiramo rezultat "strace". Pošto nije moguće znati u napred koji dečiji proces će služiti zahtev mail.php, onda moramo tragati za roditeljskim i svim dečijim procesima. Opcija "-f" koju ima "strace" će pratiti sve dečije procese koji su kreirani od strane već praćenog procesa. Evo kako to ide ... Prvo zaustavimo Apache pa ga ponovo pokrenemo sa "strace".
[root@dns1 root]# strace -f -o trace.txt /etc/rc.d/init.d/httpd start
Opcija "-o" će sačuvati rezultat u "trace.txt" fajl. Sada ponovo idi na test PHP stranu kroz brouser. Stopiraj "strace" i resetuj Apache kao obično. Možda je neophodno poslati SIGKILL signal to strace proces, pošto hvata neke signale kroz poslovanje terminala. Hajde sada da pogledamo rezultate iz trace.txt fajla.
[root@dns1 root]# grep mail.php trace.txt
21837 read(7, "GET /mail.php HTTP/1.1\r\nUser-Age"..., 4096) = 472
21837 stat64("/var/www/virtdomain/mail.php", {st_mode=S_IFREG|0644, st_size=587, ...}) = 0
Jasno je da Apache dečiji proces sa PID 21837 služi naš mail.php zahtev.
Sada koristi "grep" komandu za 21837 na trace.txt.
Sledi relevantni rezultat.
21837 chdir("/var/www/virtdomaint") = 0
21837 open("/var/www/virtdomain/mail.php", O_RDONLY) = 8
.
.
.
21837 fork() = 21844
Poslednja linija pokazuje da dečiji proces se račva u novi proces sa PID 21844.
Ponovo koristi "grep" za 21844 na trace.txt i vidi šta radi.
21844 execve("/bin/sh", ["sh", "-c", "/usr/sbin/sendmail -t -i"], [/* 21 vars */]) = -1 EACCES (Permission denied)
Pa da, proces se koristi za slanje pošte koristeći /usr/sbin/sendmail, ali nema dovoljna ovlašćenja za to.
Sendmail ovlašćenja su dobra, ali provera /bin/sh pokazuje da ima 770 sa vlasnikom root.root.
Pošto korisnik "apache" pokreće Apache dečiji proces, on nema čitajuća i izvršna ovlašćenja na /bin/sh, pa otuda ovaj problem.
Promena /bin/sh ovlašćenja na 755 rešava problem.
[ Sklon sam pokađanju zašto su ovlašćenja pogrešna. Možda se neko igra sa tvojim sistemom. -- Steve Brown ] Zaključak Sa osnovnim znanjem Apache i koristeći strace, provalili smo šta je uzrok problema i rešili smo ga. Strace je program za opštu upotrebu i može se koristiti za rešavanje problema bilo kog softvera. Strace i GDB (GNU Debugger) su veoma korisni u rešavanju problema sistema. Ovde je članka koji o tome govori. Napomena prevodioca: Ја sam 100% amater u prevođenju i veoma se dvoumim kada treba da prevedem neke reči karakteristične za oblast računara. Biće mi drago ako ima onih koji su veštiji u prevođenju i voljni da razvijaju ovaj sajt. | |||