Tarkvara juurutamise silumine strace'iga

Tarkvara juurutamise silumine strace'iga

Minu igapäevatöö on enamasti tarkvara juurutamine, mis tähendab, et veedan palju aega, et vastata järgmistele küsimustele:

  • See tarkvara töötab arendaja jaoks, kuid mitte minu jaoks. Miks?
  • Eile see tarkvara minu jaoks töötas, aga täna mitte. Miks?

See on teatud tüüpi silumine, mis erineb veidi tavalisest tarkvara silumisest. Tavaline silumine on seotud koodi loogikaga, kuid juurutamise silumine on seotud koodi ja keskkonna vastasmõjuga. Isegi kui probleemi juur on loogikaviga, tähendab see, et ühel masinal kõik töötab, teises mitte, seda, et probleem on kuidagi keskkonnas.

Nii et tavaliste silumistööriistade asemel nagu gdb Mul on juurutamise silumiseks erinevad tööriistad. Ja minu lemmiktööriist sellise probleemi lahendamiseks nagu "Miks see tarkvara minu jaoks ei tööta?" helistas kiirus.

Mis on strace?

kiirus on "süsteemikõnede jälgimise" tööriist. See loodi algselt Linuxi jaoks, kuid samu silumisnippe saab teha ka teiste süsteemide tööriistadega (DTrace või kttrace).

Põhirakendus on väga lihtne. Peate lihtsalt käivitama strace mis tahes käsuga ja see kustutab kõik süsteemikutsed (kuigi esmalt peate selle tõenäoliselt ise installima kiirus):

$ strace echo Hello
...Snip lots of stuff...
write(1, "Hellon", 6)                  = 6
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

Mis on need süsteemikutsed? See on midagi nagu API operatsioonisüsteemi tuuma jaoks. Kunagi oli tarkvaral otsene juurdepääs riistvarale, millel see töötas. Kui näiteks oli vaja midagi ekraanile kuvada, mängis see videoseadmete portide või mälukaardistatud registritega. Kui multitegumtööga arvutisüsteemid muutusid populaarseks, valitses kaos, kuna erinevad rakendused võitlesid riistvara pärast. Ühe rakenduse vead võivad kahjustada teisi, kui mitte kogu süsteemi. Seejärel ilmusid protsessorisse privileegrežiimid (või “helinakaitse”). Kernel sai kõige privilegeeritud: see sai täieliku juurdepääsu riistvarale, tekitades vähem privilegeeritud rakendusi, mis pidid juba süsteemikutsete kaudu riistvaraga suhtlemiseks taotlema tuumalt juurdepääsu.

Binaarsel tasemel erineb süsteemikutse lihtsast funktsioonikutsest veidi, kuid enamik programme kasutab standardteegi ümbrist. Need. POSIX C standardteek sisaldab funktsioonikutset kirjuta (), mis sisaldab kogu süsteemikõne arhitektuurispetsiifilist koodi kirjutama.

Tarkvara juurutamise silumine strace'iga

Lühidalt öeldes toimub igasugune suhtlus rakenduse ja selle keskkonna (arvutisüsteemide) vahel süsteemikutsete kaudu. Seega, kui tarkvara töötab ühes masinas, kuid mitte teises, oleks hea vaadata süsteemikõnede jälgimise tulemusi. Täpsemalt on siin loetelu tüüpilistest punktidest, mida saab analüüsida süsteemikõne jälgimise abil:

  • Konsooli I/O
  • Võrgu I/O
  • Juurdepääs failisüsteemile ja faili sisend/väljund
  • Protsessi lõime eluea haldamine
  • Madala taseme mäluhaldus
  • Juurdepääs konkreetsetele seadme draiveritele

Millal strace'i kasutada?

Teoorias, kiirus kasutatakse mis tahes programmiga kasutajaruumis, sest iga kasutajaruumis olev programm peab tegema süsteemikutseid. See töötab tõhusamalt koos kompileeritud madala taseme programmidega, kuid töötab ka kõrgetasemeliste keeltega, nagu Python, kui saate käitusajast ja tõlgist tulenevat lisamüra vähendada.

Kogu oma hiilguses kiirus avaldub sellise tarkvara silumisel, mis töötab ühes masinas hästi, aga lakkab äkitselt töötamast teises, produtseerides ebamääraseid sõnumeid failide, lubade või ebaõnnestunud katsete täitmisel mingite käskude või millegi muu kohta... Kahju, aga ei tööta. kombineerida nii hästi kõrgetasemeliste probleemidega, nagu sertifikaadi kinnitamise vead. Tavaliselt nõuab see kombinatsiooni kiirus, Mõnikord ltrace ja kõrgema taseme tööriistad (nt käsurea tööriist openssl sertifikaadi silumiseks).

Näitena kasutame eraldiseisvat serverit, kuid süsteemikõnede jälgimist saab sageli teha keerukamatel juurutusplatvormidel. Peate lihtsalt valima õiged tööriistad.

Lihtne silumisnäide

Oletame, et soovite käivitada hämmastavat serverirakendust foo ja see on see, milleni jõuate:

$ foo
Error opening configuration file: No such file or directory

Ilmselt ei leidnud see teie kirjutatud konfiguratsioonifaili. See juhtub seetõttu, et mõnikord alistavad paketihaldurid rakenduse kompileerimisel eeldatava faili asukoha. Ja kui järgite ühe distributsiooni installijuhendit, leiate teisest failist täiesti erinevad failid, kui ootasite. Probleemi saab mõne sekundiga lahendada, kui veateade ütleb, kust konfiguratsioonifaili otsida, kuid seda ei juhtu. Kust siis vaadata?

Kui teil on juurdepääs lähtekoodile, saate seda lugeda ja kõike teada saada. Hea varuplaan, kuid mitte kõige kiirem lahendus. Võite kasutada samm-sammult silurit nagu gdb ja vaadake, mida programm teeb, kuid palju tõhusam on kasutada tööriista, mis on spetsiaalselt loodud keskkonnaga suhtlemise näitamiseks: kiirus.

Väljund kiirus võib tunduda üleliigne, kuid hea uudis on see, et enamikku neist saab ohutult ignoreerida. Sageli on kasulik kasutada operaatorit -o, et salvestada jälgimistulemused eraldi faili:

$ strace -o /tmp/trace foo
Error opening configuration file: No such file or directory
$ cat /tmp/trace
execve("foo", ["foo"], 0x7ffce98dc010 /* 16 vars */) = 0
brk(NULL)                               = 0x56363b3fb000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=25186, ...}) = 0
mmap(NULL, 25186, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2f12cf1000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "177ELF2113 3 > 1 260A2 "..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1824496, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2f12cef000
mmap(NULL, 1837056, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2f12b2e000
mprotect(0x7f2f12b50000, 1658880, PROT_NONE) = 0
mmap(0x7f2f12b50000, 1343488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x22000) = 0x7f2f12b50000
mmap(0x7f2f12c98000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16a000) = 0x7f2f12c98000
mmap(0x7f2f12ce5000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b6000) = 0x7f2f12ce5000
mmap(0x7f2f12ceb000, 14336, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f2f12ceb000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7f2f12cf0500) = 0
mprotect(0x7f2f12ce5000, 16384, PROT_READ) = 0
mprotect(0x56363b08b000, 4096, PROT_READ) = 0
mprotect(0x7f2f12d1f000, 4096, PROT_READ) = 0
munmap(0x7f2f12cf1000, 25186)           = 0
openat(AT_FDCWD, "/etc/foo/config.json", O_RDONLY) = -1 ENOENT (No such file or directory)
dup(2)                                  = 3
fcntl(3, F_GETFL)                       = 0x2 (flags O_RDWR)
brk(NULL)                               = 0x56363b3fb000
brk(0x56363b41c000)                     = 0x56363b41c000
fstat(3, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x8), ...}) = 0
write(3, "Error opening configuration file"..., 60) = 60
close(3)                                = 0
exit_group(1)                           = ?
+++ exited with 1 +++

Ligikaudu kogu väljundi esimene leht kiirus - Tavaliselt on see madalal tasemel ettevalmistus stardiks. (Palju kõnesid mmap, mprotect, sulepea näiteks madala taseme mälu tuvastamiseks ja dünaamiliste teekide kuvamiseks.) Tegelikult väljundi silumise ajal kiirus Parem on lugeda päris lõpust. Allpool on väljakutse kirjutama, mis kuvab veateate. Vaatame ülalt ja näeme esimest vigast süsteemikõnet - kõnet openat, mis annab vea ENOENT ("faili või kataloogi ei leitud") proovib avada /etc/foo/config.json. Siin peaks olema konfiguratsioonifail.

See oli vaid näide, kuid ma ütleksin, et 90% ajast, mida ma kasutan kiirus, pole midagi palju raskemat teha kui see. Allpool on täielik samm-sammuline silumisjuhend:

  • Ärritage programmis ilmunud ebamäärase teate pärast süsteemi-y vea kohta
  • Taaskäivitage programm nupuga kiirus
  • Leidke jälgimistulemustest veateade
  • Minge kõrgemale, kuni tabate esimest ebaõnnestunud süsteemikõnet

On väga tõenäoline, et toimingus 4 tehtud süsteemikutse paljastab, mis valesti läks.

Näpunäited

Enne keerulisema silumise näite näitamist näitan teile mõnda nippi tõhusaks kasutamiseks kiirus:

mees on su sõber

Paljudes *nix süsteemides saab käivitamise abil hankida tuumale suunatud süsteemikutsete täieliku loendi mees syscalls. Näete selliseid asju nagu brk (2), mis tähendab, et käivitades saate rohkem teavet mees 2 brk.

Väike reha: mees 2 kahvel näitab mulle kesta lehte kahvel () в GNU libc, mida, selgub, rakendatakse helistades kloon (). Kõne semantika kahvel jääb samaks, kui kirjutate programmi kasutades kahvel ()ja jälgige – ma ei leia ühtegi kõnet kahvel, nende asemele tuleb kloon (). Sellised rehad ajavad sind segadusse ainult siis, kui hakkad allikat väljundiga võrdlema kiirus.

Väljundi faili salvestamiseks kasutage -o

kiirus võib genereerida ulatuslikku väljundit, mistõttu on sageli kasulik jäljetulemused salvestada eraldi failidesse (nagu ülaltoodud näites). See aitab vältida ka programmi väljundi ja väljundi segi ajamist kiirus konsoolis.

Rohkemate argumentide andmete vaatamiseks kasutage -s

Võib-olla olete märganud, et veateate teist poolt ülaltoodud näitejäljes ei kuvata. See on sellepärast kiirus Vaikimisi kuvatakse ainult stringargumendi esimesed 32 baiti. Kui soovite rohkem näha, lisage midagi sarnast -s 128 kõnele kiirus.

-y muudab failide, pistikupesade jms jälgimise lihtsamaks.

"Kõik on fail" tähendab, et *nix-süsteemid teevad kõik sisend-/väljundid failideskriptoreid kasutades, olenemata sellest, kas see kehtib faili või võrgu või protsessidevaheliste torude kohta. See on programmeerimiseks mugav, kuid raskendab tegelikult toimuva jälgimise, kui näete ühist lugenud и kirjutama süsteemi kõne jälgimise tulemustes.

Operaatori lisamisega -y, siis sunnid kiirus lisage igale väljundis olevale failikirjeldusele märkus, millele see viitab.

Ühendage juba töötava protsessiga -p**

Nagu näete allolevast näitest, peate mõnikord jälgima juba töötavat programmi. Kui on teada, et see töötab protsessina 1337 (näiteks väljundist ps), siis saate seda jälgida järgmiselt:

$ strace -p 1337
...system call trace output...

Võimalik, et vajate juurõigusi.

Lapse protsesside jälgimiseks kasutage -f

kiirus Vaikimisi jälgib see ainult ühte protsessi. Kui see protsess tekitab alamprotsesse, on alamprotsessi loomise süsteemikutset näha, kuid alamprotsessi süsteemikutseid ei kuvata.

Kui arvate, et viga on alamprotsessis, kasutage avaldust -f, võimaldab see selle jälgimist. Selle negatiivne külg on see, et väljund ajab teid veelgi segadusse. Millal kiirus jälgib ühte protsessi või üht lõime, näitab see üht kõnesündmuste voogu. Kui see jälgib mitut protsessi korraga, võite näha kõne algust, mille katkestab sõnum , siis - hulk kutseid teistele täitmisharudele ja alles siis - esimese lõpp <…foocall jätkus>. Või jagage kõik jäljetulemused erinevatesse failidesse, kasutades ka operaatorit -ff (üksikasjad sisse juhend edasi kiirus).

Filtreerige jäljed kasutades -e

Nagu näete, on jälje tulemuseks tõeline hunnik kõiki võimalikke süsteemikutseid. Lipp -e Saate filtreerida jälgi (vt juhtpositsiooni edasi kiirus). Peamine eelis on see, et filtreeritud jälgede käivitamine on kiirem kui täielik jälg ja seejärel grep`at. Kui aus olla, siis ma peaaegu alati ei hooli.

Kõik vead pole halvad

Lihtne ja levinud näide on programm, mis otsib faili mitmest kohast korraga, näiteks kest, mis otsib käivitatavat faili sisaldavat kataloogi:

$ strace sh -c uname
...
stat("/home/user/bin/uname", 0x7ffceb817820) = -1 ENOENT (No such file or directory)
stat("/usr/local/bin/uname", 0x7ffceb817820) = -1 ENOENT (No such file or directory)
stat("/usr/bin/uname", {st_mode=S_IFREG|0755, st_size=39584, ...}) = 0
...

Asjakohaste vigade leidmiseks sobivad hästi sellised heuristika nagu „viimane ebaõnnestunud päring enne veast teatamist”. Olgu kuidas on, loogiline on alustada päris lõpust.

C-programmeerimise õpetused aitavad teil mõista süsteemikõnesid.

Standardkõned C-teegidesse ei ole süsteemikutsed, vaid ainult õhuke pinnakiht. Seega, kui mõistate vähemalt veidi, kuidas ja mida C-s teha, on teil lihtsam mõista süsteemikõne jälgimise tulemusi. Näiteks on teil probleeme võrgusüsteemide kõnede silumisega, vaadake sama klassikat Bija võrguprogrammeerimise juhend.

Keerulisem silumisnäide

Ma juba ütlesin, et lihtsa silumise näide on näide sellest, millega ma töötades pean enamasti tegelema kiirus. Mõnikord on siiski vaja tõelist uurimist, nii et siin on näide täpsemast silumisest.

bcron - ülesannete töötlemise ajakava, teine ​​*nix deemoni teostus cron. See on serverisse installitud, kuid kui keegi proovib ajakava muuta, juhtub see järgmiselt.

# crontab -e -u logs
bcrontab: Fatal: Could not create temporary file

Olgu, see tähendab bcron üritas kirjutada teatud faili, kuid see ei õnnestunud ja ta ei tunnista, miks. Paljastamine kiirus:

# strace -o /tmp/trace crontab -e -u logs
bcrontab: Fatal: Could not create temporary file
# cat /tmp/trace
...
openat(AT_FDCWD, "bcrontab.14779.1573691864.847933", O_RDONLY) = 3
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f82049b4000
read(3, "#Ansible: logsaggn20 14 * * * lo"..., 8192) = 150
read(3, "", 8192)                       = 0
munmap(0x7f82049b4000, 8192)            = 0
close(3)                                = 0
socket(AF_UNIX, SOCK_STREAM, 0)         = 3
connect(3, {sa_family=AF_UNIX, sun_path="/var/run/bcron-spool"}, 110) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f82049b4000
write(3, "156:Slogs #Ansible: logsaggn20 1"..., 161) = 161
read(3, "32:ZCould not create temporary f"..., 8192) = 36
munmap(0x7f82049b4000, 8192)            = 0
close(3)                                = 0
write(2, "bcrontab: Fatal: Could not creat"..., 49) = 49
unlink("bcrontab.14779.1573691864.847933") = 0
exit_group(111)                         = ?
+++ exited with 111 +++

Päris lõpus on veateade kirjutama, kuid seekord on midagi teisiti. Esiteks puudub asjakohane süsteemikõne tõrge, mis tavaliselt ilmneb enne seda. Teiseks on selge, et kuskil on keegi veateadet juba lugenud. Näib, et tegelik probleem on kusagil mujal ja bcrontab lihtsalt taasesitab sõnumi.

Kui vaatate mees 2 lugenud, näete, et esimene argument (3) on faili deskriptor, mida *nix kasutab kogu I/O töötlemiseks. Kuidas teada saada, mida failideskriptor 3 tähistab? Sel konkreetsel juhul võite joosta kiirus koos operaatoriga -y (vt ülal) ja see ütleb teile automaatselt, kuid selliste asjade väljaselgitamiseks on kasulik teada, kuidas jäljetulemusi lugeda ja sõeluda.

Failideskriptori allikaks võib olla üks paljudest süsteemikutstest (kõik sõltub sellest, mille jaoks see deskriptor on mõeldud – konsool, võrgupesa, fail ise või midagi muud), kuid olgu kuidas on, otsime helistab, tagastades numbri 3 (st otsime jälgimistulemustest „= 3”). Selles tulemuses on neist 2: openat päris tipus ja pesa Keskel. openat avab faili, kuid lähedal(3) näitab, et see sulgub uuesti. (Rake: failikirjeldusi saab nende avamisel ja sulgemisel uuesti kasutada). Helistama pesa () sobib, sest see on viimane loe (), ja selgub, et bcrontab töötab millegagi läbi pesa. Järgmine rida näitab, et faili deskriptor on seotud unixi domeeni pesa teel /var/run/bcron-spool.

Seega peame leidma sellega seotud protsessi unixi pesa teisel pool. Selleks on paar korralikku nippi, mis mõlemad on kasulikud serveri juurutamise silumiseks. Esimene on kasutada netstat või uuem ss (pistikupesa olek). Mõlemad käsud näitavad süsteemi aktiivseid võrguühendusi ja võtavad avalduse -l kuulamispesade, aga ka operaatori kirjeldamiseks -p pistikupesaga ühendatud programmide kuvamiseks kliendina. (On palju rohkem kasulikke valikuid, kuid need kaks on selle ülesande jaoks piisavad.)

# ss -pl | grep /var/run/bcron-spool
u_str LISTEN 0   128   /var/run/bcron-spool 1466637   * 0   users:(("unixserver",pid=20629,fd=3))

See viitab sellele, et kuulaja on käsk inixserver, töötab protsessi ID-ga 20629. (Ja juhuslikult kasutab see soklana failideskriptorit 3.)

Teine tõeliselt kasulik tööriist sama teabe leidmiseks on nn lsof. See loetleb kõik süsteemis avatud failid (või failideskriptorid). Või saate teavet ühe konkreetse faili kohta:

# lsof /var/run/bcron-spool
COMMAND   PID   USER  FD  TYPE  DEVICE              SIZE/OFF  NODE    NAME
unixserve 20629 cron  3u  unix  0x000000005ac4bd83  0t0       1466637 /var/run/bcron-spool type=STREAM

Protsess 20629 on pikaealine server, nii et saate selle külge ühendada kiirus kasutades midagi sarnast strace -o /tmp/trace -p 20629. Kui redigeerite cron-tööd teises terminalis, saate veaga jälitusväljundi. Ja siin on tulemus:

accept(3, NULL, NULL)                   = 4
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7faa47c44810) = 21181
close(4)                                = 0
accept(3, NULL, NULL)                   = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=21181, si_uid=998, si_status=0, si_utime=0, si_stime=0} ---
wait4(0, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG|WSTOPPED, NULL) = 21181
wait4(0, 0x7ffe6bc36764, WNOHANG|WSTOPPED, NULL) = -1 ECHILD (No child processes)
rt_sigaction(SIGCHLD, {sa_handler=0x55d244bdb690, sa_mask=[CHLD], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7faa47ab9840}, {sa_handler=0x55d244bdb690, sa_mask=[CHLD], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7faa47ab9840}, 8) = 0
rt_sigreturn({mask=[]})                 = 43
accept(3, NULL, NULL)                   = 4
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7faa47c44810) = 21200
close(4)                                = 0
accept(3, NULL, NULL)                   = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=21200, si_uid=998, si_status=111, si_utime=0, si_stime=0} ---
wait4(0, [{WIFEXITED(s) && WEXITSTATUS(s) == 111}], WNOHANG|WSTOPPED, NULL) = 21200
wait4(0, 0x7ffe6bc36764, WNOHANG|WSTOPPED, NULL) = -1 ECHILD (No child processes)
rt_sigaction(SIGCHLD, {sa_handler=0x55d244bdb690, sa_mask=[CHLD], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7faa47ab9840}, {sa_handler=0x55d244bdb690, sa_mask=[CHLD], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7faa47ab9840}, 8) = 0
rt_sigreturn({mask=[]})                 = 43
accept(3, NULL, NULL

(Viimane aktsepteeri () ei lõpetata jälgimisel.) Jällegi ei sisalda see tulemus kahjuks otsitavat viga. Me ei näe ühtegi sõnumit, mille bcrontag pistikupesasse saadab või sealt vastu võtab. Selle asemel täielik protsessi juhtimine (kloonida, oota 4, SIGCHLD jne) See protsess tekitab alamprotsessi, mis, nagu võite arvata, teeb tegelikku tööd. Ja kui teil on vaja tema jälgedele jõuda, lisage kõne joon -f. Selle leiame, kui otsime uuest tulemusest tõrketeadet strace abil -f -o /tmp/trace -p 20629:

21470 openat(AT_FDCWD, "tmp/spool.21470.1573692319.854640", O_RDWR|O_CREAT|O_EXCL, 0600) = -1 EACCES (Permission denied) 
21470 write(1, "32:ZCould not create temporary f"..., 36) = 36
21470 write(2, "bcron-spool[21470]: Fatal: logs:"..., 84) = 84
21470 unlink("tmp/spool.21470.1573692319.854640") = -1 ENOENT (No such file or directory)
21470 exit_group(111)                   = ?
21470 +++ exited with 111 +++

See on nüüd midagi. Protsess 21470 saab teel faili loomisel tõrketeate "juurdepääs keelatud" tmp/spool.21470.1573692319.854640 (seoses praeguse töökataloogiga). Kui me vaid teaksime praegust töökataloogi, teaksime ka täielikku teed ja saaksime aru, miks protsess ei saa selles oma ajutist faili luua. Kahjuks on protsess juba lõppenud, nii et te ei saa lihtsalt kasutada lsof -p 21470 praeguse kataloogi leidmiseks, kuid võite töötada ka vastupidises suunas - otsige PID 21470 süsteemikutseid, mis muudavad kataloogi. (Kui neid pole, peab PID 21470 olema need pärinud oma vanemalt ja see on juba läbi lsof -p ei saa teada.) See süsteemikutse on chdir (mida on tänapäevaste veebiotsingumootorite abil lihtne välja selgitada). Ja siin on jälgimistulemuste põhjal tehtud pöördotsingu tulemus kuni serveri PID 20629ni:

20629 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7faa47c44810) = 21470
...
21470 execve("/usr/sbin/bcron-spool", ["bcron-spool"], 0x55d2460807e0 /* 27 vars */) = 0
...
21470 chdir("/var/spool/cron")          = 0
...
21470 openat(AT_FDCWD, "tmp/spool.21470.1573692319.854640", O_RDWR|O_CREAT|O_EXCL, 0600) = -1 EACCES (Permission denied) 
21470 write(1, "32:ZCould not create temporary f"..., 36) = 36
21470 write(2, "bcron-spool[21470]: Fatal: logs:"..., 84) = 84
21470 unlink("tmp/spool.21470.1573692319.854640") = -1 ENOENT (No such file or directory)
21470 exit_group(111)                   = ?
21470 +++ exited with 111 +++

(Kui olete eksinud, võiksite lugeda minu eelmist postitust *nixi protsessihalduse ja kestade kohta.) Seega ei saanud serveri PID 20629 luba teel faili loomiseks /var/spool/cron/tmp/spool.21470.1573692319.854640. Tõenäoliselt on selle põhjuseks klassikalised failisüsteemi loa seaded. Kontrollime:

# ls -ld /var/spool/cron/tmp/
drwxr-xr-x 2 root root 4096 Nov  6 05:33 /var/spool/cron/tmp/
# ps u -p 20629
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
cron     20629  0.0  0.0   2276   752 ?        Ss   Nov14   0:00 unixserver -U /var/run/bcron-spool -- bcron-spool

Sinna on koer maetud! Server töötab kasutaja cronina, kuid ainult administraatoril on õigus kataloogi kirjutada /var/spool/cron/tmp/. Lihtne käsk chown cron /var/spool/cron/tmp/ sunnib bcron korralikult töötama. (Kui see ei olnud probleem, siis järgmine kõige tõenäolisem kahtlusalune on tuuma turvamoodul nagu SELinux või AppArmor, seega kontrolliksin kerneli sõnumite logi dmesg.)

Kogusummas

Süsteemikõnede jäljed võivad algajale olla ülekaalukad, kuid loodan, et olen näidanud, et need on kiire viis terve klassi levinumate juurutusprobleemide silumiseks. Kujutage ette, et proovite mitut protsessi siluda bcronkasutades samm-sammult silurit.

Jäljetulemuste sõelumine mööda süsteemikutsete ahelat nõuab oskusi, kuid nagu ma ütlesin, peaaegu alati, kasutades kiirus, saan lihtsalt jäljetulemuse ja otsin vigu alates lõpust. Igatahes kiirus aitab mul silumisel palju aega kokku hoida. Loodan, et see on kasulik ka teile.

Allikas: www.habr.com

Lisa kommentaar