Debuggen software ynset mei strace

Debuggen software ynset mei strace

Myn wurkdei is meast software-ynset, wat betsjut dat ik in protte tiid besteegje oan it besykjen om fragen te beantwurdzjen lykas:

  • Dizze software wurket foar de ûntwikkelder, mar net foar my. Wêrom?
  • Juster wurke dizze software foar my, mar hjoed docht it net. Wêrom?

Dit is in soarte fan debuggen dy't wat oars is fan gewoane software-debuggen. Reguliere debuggen giet oer de logika fan 'e koade, mar ynset-debuggen giet oer de ynteraksje tusken de koade en de omjouwing. Sels as de woartel fan it probleem in logyske flater is, betsjut it feit dat alles op ien masine wurket en net op in oare dat it probleem op ien of oare manier yn 'e omjouwing is.

Dus ynstee fan de gewoane debuggen ark lykas gdb Ik haw in oare set ark foar debuggen ynset. En myn favorite ark foar it omgean mei it probleem lykas "Wêrom wurket dizze software net foar my?" neamd strace.

Wat is strace?

strace is in ark foar "systeemoprop tracing". It is oarspronklik makke foar Linux, mar deselde debuggen kinne wurde dien mei ark foar oare systemen (DTrace of ktrace).

De basisapplikaasje is heul ienfâldich. Jo moatte gewoan strace útfiere mei elk kommando en it sil alle systeemoproppen dumpe (hoewol jo earst it wierskynlik sels moatte ynstallearje strace):

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

Wat binne dizze systeemoproppen? Dit is wat as in API foar de kernel fan it bestjoeringssysteem. Eartiids hie software direkte tagong ta de hardware wêrop it rûn. As it bygelyks wat op it skerm werjaan moast, spile it mei havens of registers foar fideo-apparaten yn kaart brocht troch it ûnthâld. Doe't multitasking-kompjûtersystemen populêr waarden, hearske gaos as ferskate applikaasjes fochten oer de hardware. Flaters yn ien applikaasje kinne oaren delbringe, as net it hiele systeem. Dêrnei ferskynden privileezjemodi (as "ringbeskerming") yn 'e CPU. De kernel waard de meast befoarrjochte: it krige folsleine tagong ta de hardware, wêrtroch't minder befoarrjochte applikaasjes spawnden dy't al tagong fan 'e kernel moasten freegje om te ynteraksje mei de hardware fia systeemoproppen.

Op it binêre nivo is in systeemoprop wat oars as in ienfâldige funksjeoprop, mar de measte programma's brûke in wrapper yn 'e standertbibleteek. Dy. de POSIX C standert bibleteek befettet in funksje oprop skriuwe(), dy't alle arsjitektuer-spesifike koade befettet foar de systeemoprop skriuwe.

Debuggen software ynset mei strace

Koartsein, elke ynteraksje tusken in applikaasje en har omjouwing (komputersystemen) wurdt útfierd troch systeemoproppen. Dêrom, as software wurket op ien masine, mar net op in oar, soe it goed wêze om te sjen nei de resultaten fan systeemoprop tracing. Mear spesifyk is hjir in list mei typyske punten dy't kinne wurde analysearre mei in systeemopropspoar:

  • Konsole I/O
  • Netwurk I/O
  • Triemsysteem tagong en triem I/O
  • Behear fan it libben fan in proses thread
  • Leech-nivo ûnthâld behear
  • Tagong ta spesifike apparaat drivers

Wannear te brûken strace?

Yn teory, strace brûkt mei elk programma yn brûkersromte, om't elk programma yn brûkersromte systeemoproppen moat meitsje. It wurket effisjinter mei kompilearre programma's op leech nivo, mar it wurket ek mei talen op heech nivo lykas Python as jo it ekstra lûd kinne snije fan 'e runtime en tolk.

Yn al syn gloarje strace manifestearret him by it debuggen fan software dy't goed wurket op ien masine, mar ynienen ophâldt mei wurkjen op in oare, it produsearjen fan vague berjochten oer triemmen, tagongsrjochten, of mislearre besykjen om guon kommando's of wat oars út te fieren ... It is spitich, mar it docht net kombinearje sa goed mei problemen op heech nivo lykas sertifikaatferifikaasjeflaters. Meastal fereasket dit in kombinaasje stracesomtiden ltrace en ark op heger nivo (lykas it kommandorigelark openssl om it sertifikaat te debuggen).

Wy sille in standalone tsjinner as foarbyld brûke, mar systeemoprop tracing kin faak dien wurde op mear komplekse ynsetplatfoarms. Jo moatte gewoan de juste ark kieze.

Foarbyld fan Simple debuggen

Litte wy sizze dat jo de geweldige serverapplikaasje foo wolle útfiere, en dit is wêrmei jo einigje:

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

Blykber koe it it konfiguraasjetriem dat jo skreaun hawwe net fine. Dit bart om't soms as pakketbehearders in applikaasje kompilearje, se de ferwachte bestânlokaasjes oerskriuwe. En as jo de ynstallaasjegids folgje foar ien distribúsje, fine jo yn in oare bestannen folslein oars as wêr't jo ferwachte hawwe. It probleem koe wurde oplost yn in pear sekonden as it flater berjocht fertelde wêr't te sykjen foar de konfiguraasje triem, mar it docht net. Dus wêr te sjen?

As jo ​​tagong hawwe ta de boarnekoade, kinne jo it lêze en alles fine. In goed reservekopyplan, mar net de rapste oplossing. Jo kinne taflecht ta in stap-foar-stap debugger lykas gdb en sjoch wat it programma docht, mar it is folle effektiver om in ark te brûken dat spesifyk is ûntworpen om ynteraksje mei de omjouwing te sjen: strace.

konklúzje strace kin lykje oerstallich, mar it goede nijs is dat it grutste part fan it kin feilich negearre. It is faak nuttich om de operator -o te brûken om spoarresultaten op te slaan yn in apart bestân:

$ 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 +++

Likernôch de hiele earste side fan útfier strace - Dit is normaal de tarieding op leech nivo foar lansearring. (In protte oproppen mmap, mprotect, skever foar dingen lykas it opspoaren fan leech-nivo ûnthâld en it werjaan fan dynamyske bibleteken.) Eins, by it debuggen fan de útfier strace It is better om fan 'e ein te lêzen. Der sil in útdaging hjirûnder skriuwe, dy't in flaterberjocht toant. Wy sjogge hjirboppe en sjogge de earste ferkearde systeemoprop - de oprop iepenet, dy't smyt in flater ENOENT ("bestân of map net fûn") besykje te iepenjen /etc/foo/config.json. Dit is wêr't it konfiguraasjetriem wêze moat.

Dit wie gewoan in foarbyld, mar ik soe sizze 90% fan 'e tiid dat ik brûk strace, der is neat folle dreger te dwaan as dit. Hjirûnder is in folsleine stap-foar-stap debuggengids:

  • Wês oerstjoer fanwege in vague berjocht oer in systeem-y flater fan in programma
  • Restart it programma mei strace
  • Fyn it flaterberjocht yn 'e spoarresultaten
  • Gean heger oant jo de earste mislearre systeemoprop reitsje

It is heul wierskynlik dat de systeemoprop yn stap 4 sil sjen litte wat der mis gie.

Oanwizings

Foardat jo in foarbyld sjen litte fan kompleksere debuggen, sil ik jo in pear trúkjes sjen litte foar effektyf gebrûk strace:

man is dyn freon

Op in protte *nix-systemen kin in folsleine list mei systeemoproppen nei de kernel wurde krigen troch te rinnen man syscals. Jo sille dingen sjen lykas brk (2), wat betsjut dat mear ynformaasje kin wurde krigen troch te rinnen man 2 brk.

Kleine hark: man 2 fork lit my de side foar de shell sjen foarke() в GNU libc, dy't, docht bliken, wurdt útfierd troch oprop kloon (). Oprop semantyk foarke bliuwt itselde as jo in programma skriuwe mei foarke(), en rinne in spoar - ik sil net fine gjin oproppen foarke, ynstee fan harren sil der wêze kloon (). Sokke raken ferwarje jo allinich as jo de boarne begjinne te fergelykjen mei de útfier strace.

Brûk -o om de útfier te bewarjen yn in bestân

strace kin wiidweidige útfier generearje, dus it is faak nuttich om spoarresultaten yn aparte bestannen op te slaan (lykas yn it foarbyld hjirboppe). Dit helpt ek om ferwarrende programma-útfier mei útfier te foarkommen strace yn 'e konsole.

Brûk -s om mear argumintgegevens te besjen

Jo hawwe miskien opfallen dat de twadde helte fan it flaterberjocht net werjûn wurdt yn it foarbyldspoar hjirboppe. It is om't strace standert lit allinnich de earste 32 bytes fan it tekenrige argumint sjen. As jo ​​​​mear wolle sjen, foegje dan wat ta as -s 128 oan de oprop strace.

-y makket it makliker om bestannen, sockets, ensfh.

"Alles is bestân" betsjut dat *nix-systemen alle I/O dogge mei triembeskriuwers, oft dat jildt foar in bestân as in netwurk of interprocesspipes. Dit is handich foar programmearring, mar makket it lestich om by te hâlden wat der echt bart as jo gewoan sjogge lêze и skriuwe yn it systeem oprop trace resultaten.

Troch it tafoegjen fan in operator -y, do silst twinge strace annotearje elke triembeskriuwer yn 'e útfier mei in notysje fan wêr't it op wiist.

Heakje oan in al rinnend proses mei -p**

Lykas jo sille sjen út it foarbyld hjirûnder, soms moatte jo trace in programma dat al rint. As it bekend is dat it rint as proses 1337 (sizze, fanút de útfier ps), dan kinne jo it sa folgje:

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

Jo kinne root-rjochten nedich hawwe.

Brûk -f om bernprosessen te kontrolearjen

strace Standert traceart it mar ien proses. As dit proses bernprosessen opbringt, dan kin de systeemoprop om it bernproses te spawnen sjoen wurde, mar de systeemoproppen fan it bernproses wurde net werjûn.

As jo ​​tinke dat de flater is yn in bern proses, brûk dan de ferklearring -f, dit sil syn tracing ynskeakelje. It neidiel hjirfan is dat de útfier jo noch mear betize sil. Wannear strace traces ien proses of ien tried, it toant in inkele stream fan oprop eveneminten. As it meardere prosessen tagelyk traceart, kinne jo it begjin fan in oprop sjen ûnderbrutsen troch in berjocht , dan - in bosk oproppen foar oare eksekúsjetûken, en pas dan - it ein fan 'e earste <...foocall hervat>. Of splitst alle spoarresultaten yn ferskate bestannen, ek mei de operator -ff (details yn liederskip on strace).

Spoaren filterje mei -e

Sa't jo sjen kinne, is it resultaat fan it spoar in echte stapel fan alle mooglike systeemoproppen. Flagge -e Jo kinne it spoar filterje (sjoch liederskip on strace). It wichtichste foardiel is dat it flugger is om in filtere spoar út te fieren dan in folsleine spoar te dwaan en dan grep`by. Om earlik te wêzen, haw ik hast altyd neat skele.

Net alle flaters binne min

In ienfâldich en gewoan foarbyld is in programma dat op ferskate plakken tagelyk nei in bestân siket, lykas in shell op syk nei in map dy't in útfierber bestân befettet:

$ 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
...

Heuristyken lykas "lêste mislearre fersyk foar it rapportearjen fan in flater" binne goed by it finen fan relevante flaters. Hoe dan ek, it is logysk om fan 'e ein te begjinnen.

C-programmearring-tutorials kinne jo helpe om systeemoproppen te begripen.

Standert oproppen nei C biblioteken binne gjin systeem calls, mar allinnich in tinne oerflak laach. Dus, as jo op syn minst in bytsje begripe hoe en wat te dwaan yn C, sil it makliker wêze foar jo om de resultaten fan 'e systeemoprop trace te begripen. Jo hawwe bygelyks problemen mei debuggen nei netwurksystemen, sjoch op deselde klassiker Bija's Guide to Network Programming.

In mear komplekse debuggen foarbyld

Ik sei al dat it foarbyld fan ienfâldige debuggen in foarbyld is fan wêr't ik meast mei te krijen ha as ik mei wurkje strace. Soms is lykwols in wirklik ûndersyk fereaske, dus hjir is in echte foarbyld fan mear avansearre debuggen.

bcron - Scheduler foar taakferwurking, in oare ymplemintaasje fan 'e *nix-daemon Cron. It is ynstalleare op de tsjinner, mar as immen besiket it skema te bewurkjen, bart dit:

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

Okee, dat betsjut bcron besocht te skriuwen in bepaalde triem, mar it slagge net, en hy sil net tajaan wêrom. Untdekking strace:

# 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 +++

D'r is in flaterberjocht tichtby it ein skriuwe, mar dizze kear is wat oars. Earst is d'r gjin relevante systeemopropflater, dy't normaal foar dit foarkomt. As twadde is it dúdlik dat der earne al ien it flaterberjocht lêzen hat. It liket derop dat de echte probleem is earne oars, en bcrontab spilet gewoan it berjocht werom.

As jo ​​sjogge nei man 2 lêzen, kinne jo sjen dat it earste argumint (3) in triembeskriuwing is, dy't *nix brûkt foar alle I/O-ferwurking. Hoe kin ik útfine hokker triembeskriuwing 3 fertsjintwurdiget? Yn dit bysûndere gefal kinne jo rinne strace mei operator -y (sjoch hjirboppe) en it sil jo automatysk fertelle, mar om dingen lykas dit út te finen, is it handich om te witten hoe't jo trace-resultaten lêze en analysearje.

De boarne fan in triembeskriuwer kin ien fan in protte systeemoanroppen wêze (it hinget allegear ôf fan wêr't de beskriuwing foar is - in konsole, in netwurksocket, it bestân sels, of wat oars), mar hoe't it kin, wy sykje nei ropt troch 3 werom te jaan (d.w.s. wy sykje "= 3" yn 'e tracingresultaten). Yn dit resultaat binne d'r 2 fan har: iepenet op de hiel top en socket Yn it midden. iepenet iepenet de triem mar slute(3) sil dan sjen litte dat it wer slút. (Rake: triembeskriuwers kinne opnij brûkt wurde as se iepene en sluten wurde). Belje stopkontakt () geskikt omdat it de lêste earder is lêze(), en it docht bliken dat bcrontab wurket mei wat troch in socket. De folgjende rigel lit sjen dat de triembeskriuwing is assosjearre mei unix domein socket ûnderweis /var/run/bcron-spool.

Dat, wy moatte it proses fine dat ferbûn is mei unix socket oan de oare kant. D'r binne in pear kreaze trúkjes foar dit doel, dy't beide nuttich binne foar it debuggen fan server-ynset. De earste is te brûken netstat of nijer ss (socket status). Beide kommando's litte de aktive netwurkferbiningen fan it systeem sjen en de ferklearring nimme -l om harkjende sockets te beskriuwen, lykas de operator -p om programma's te werjaan dy't ferbûn binne mei de socket as kliïnt. (D'r binne folle mear nuttige opsjes, mar dizze twa binne genôch foar dizze taak.)

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

Dit suggerearret dat de harker it kommando is inixserver, rint mei proses ID 20629. (En, tafallich, brûkt it triembeskriuwing 3 as de socket.)

It twadde echt brûkbere ark foar it finen fan deselde ynformaasje wurdt neamd lsof. It listet alle iepene bestannen (as triembeskriuwers) op it systeem. Of jo kinne ynformaasje krije oer ien spesifyk bestân:

# 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

Proses 20629 is in lange-libbe tsjinner, dus jo kinne heakje it oan strace mei help fan wat as strace -o /tmp/trace -p 20629. As jo ​​in cron-taak yn in oare terminal bewurkje, krije jo in spoarútfier mei in flater. En hjir is it resultaat:

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

(Lêst oannimme() sil net foltôge wurde by tracing.) Nochris, spitigernôch, dit resultaat befettet net de flater wy sykje. Wy sjogge gjin berjochten dy't bcrontag stjoert nei of ûntfangt fan 'e socket. Ynstee, folsleine proseskontrôle (klon, wachtsje 4, SIGCHLD ensfh.) Dit proses soarget foar in bernproses, dat, lykas jo miskien riede, it echte wurk docht. En as jo har spoar moatte fange, foegje dan ta oan 'e oprop striek -f. Dit is wat wy sille fine as wy sykje nei it flaterberjocht yn it nije resultaat mei strace -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 +++

No, dat is wat. Proses 21470 ûntfangt in flater "tagong wegere" by it besykjen om in bestân op paad te meitsjen tmp/spool.21470.1573692319.854640 (oangeande de aktuele wurkmap). As wy gewoan de hjoeddeistige wurkmap wisten, soene wy ​​ek it folsleine paad kenne en kinne útfine wêrom't it proses syn tydlike bestân der net yn kin oanmeitsje. Spitigernôch is it proses al ôfsletten, dus jo kinne net gewoan brûke lsof -p 21470 om de hjoeddeistige map te finen, mar jo kinne yn 'e tsjinoerstelde rjochting wurkje - sykje nei PID 21470-systeemoproppen dy't de map feroarje. (As d'r gjin binne, moat PID 21470 se fan har âlder hawwe erfd, en dit is al troch lsof -p kin net fûn út.) Dit systeem oprop is chdir (wat maklik te finen is mei help fan moderne online sykmasines). En hjir is it resultaat fan omkearde sykopdrachten basearre op de spoarresultaten, oant de server PID 20629:

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 +++

(As jo ​​ferlern binne, wolle jo miskien myn foarige post lêze oer * nix proses behear en skulpen.) Dus, de tsjinner PID 20629 hat gjin tastimming krigen om in bestân op it paad te meitsjen /var/spool/cron/tmp/spool.21470.1573692319.854640. Meast wierskynlik is de reden hjirfoar de klassike tastimmingynstellingen foar bestânsysteem. Litte wy kontrolearje:

# 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

Dêr leit de hûn begroeven! De tsjinner rint as brûker cron, mar allinnich root hat tastimming om te skriuwen nei de map /var/spool/cron/tmp/. Ienfâldich kommando chown cron /var/spool/cron/tmp/ sil twinge bcron wurkje goed. (As dat net it probleem wie, dan is de folgjende meast wierskynlike fertochte in kernelfeiligensmodule lykas SELinux of AppArmor, dus ik soe it kernelberjochtlog kontrolearje mei dmesg.)

Totaal

Systeem oprop spoaren kin wêze oerweldigjend foar in begjinner, mar ik hoopje dat ik haw sjen litten dat se binne in flugge manier in debug in hiele klasse fan mienskiplike ynset problemen. Stel jo foar dat jo besykje in multyproses te debuggen bcronmei help fan in stap-foar-stap debugger.

It parsearjen fan spoarresultaten efterút lâns de systeemopropketen fereasket feardigens, mar lykas ik sei, hast altyd, mei help fan strace, Ik krij gewoan it spoarresultaat en sykje nei flaters begjinnend fan 'e ein. Hoe dan ek, strace helpt my in protte tiid te besparjen op debuggen. Ik hoopje dat it sil wêze nuttich foar jo ek.

Boarne: www.habr.com

Add a comment