strace менен программалык камсыздоону орнотуу

strace менен программалык камсыздоону орнотуу

Менин күнүмдүк жумушум негизинен программалык камсыздоону жайылтуу, демек, мен төмөнкү суроолорго жооп берүүгө көп убакыт коротом:

  • Бул программа иштеп чыгуучу үчүн иштейт, бирок мен үчүн эмес. Неге?
  • Кечээ бул программа мен үчүн иштеген, бирок бүгүн андай эмес. Неге?

Бул кадимки программалык мүчүлүштүктөрдү оңдоодон бир аз айырмаланган мүчүлүштүктөрдү оңдоонун бир түрү. Үзгүлтүксүз мүчүлүштүктөрдү оңдоо коддун логикасы жөнүндө, ал эми жайылтуу мүчүлүштүктөрдү оңдоо код менен чөйрөнүн ортосундагы өз ара аракеттенүү жөнүндө. Көйгөйдүн тамыры логикалык ката болсо да, баары бир машинада иштебей, экинчисинде иштебей турганы көйгөй кандайдыр бир чөйрөдө экенин билдирет.

Ошентип, кадимки мүчүлүштүктөрдү оңдоо куралдарынын ордуна gdb Менде мүчүлүштүктөрдү оңдоо үчүн башка куралдар топтому бар. Ал эми көйгөйдү чечүү үчүн менин сүйүктүү куралым "Эмне үчүн бул программа мен үчүн иштебейт?" чакырды strace.

strace деген эмне?

strace "системалык чалууларды көзөмөлдөө" куралы болуп саналат. Ал башында Linux үчүн түзүлгөн, бирок ошол эле мүчүлүштүктөрдү оңдоо ыкмаларын башка системалар үчүн куралдар менен жасоого болот (DTrace же ktration).

Негизги колдонмо абдан жөнөкөй. Сиз жөн гана каалаган буйрук менен strace иштетишиңиз керек жана ал бардык тутумдук чалууларды жок кылат (бирок адегенде аны өзүңүз орнотуп алышыңыз керек болот. 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 +++

Бул системанын чалуулары кандай? Бул операциялык тутумдун өзөгү үчүн API сыяктуу нерсе. Бир жолу, программалык камсыздоо ал иштеп жаткан аппараттык жабдыкка түз кире алган. Эгер, мисалы, экранда бир нерсени көрсөтүү керек болсо, ал порттор же видео түзүлүштөр үчүн эстутум картасына түшүрүлгөн регистрлер менен ойногон. Көп милдеттүү компьютер системалары популярдуу болуп калганда, ар кандай тиркемелер аппараттык камсыздоо үчүн күрөшкөндүктөн, башаламандык өкүм сүргөн. Бир тиркемедеги каталар бүтүндөй системаны эмес, башкаларды да кыйратышы мүмкүн. Андан кийин CPUда артыкчылык режимдери (же "шакек коргоо") пайда болду. Ядро эң артыкчылыктуу болуп калды: ал аппараттык жабдыкка толук мүмкүнчүлүк алды, азыраак артыкчылыктуу тиркемелерди пайда кылды, алар системалык чалуулар аркылуу аппараттык камсыздоо менен өз ара аракеттенүү үчүн ядродон кирүүнү суранышы керек болчу.

Бинардык деңгээлде тутумдук чалуу жөнөкөй функциялык чакыруудан бир аз айырмаланат, бирок көпчүлүк программалар стандарттык китепканада орогучту колдонушат. Ошол. POSIX C стандарттык китепканасы функция чакырыгын камтыйт жазуу (), ал тутумдук чалуу үчүн архитектурага тиешелүү бардык кодду камтыйт жазуу.

strace менен программалык камсыздоону орнотуу

Кыскача айтканда, тиркеме менен анын чөйрөсү (компьютер системалары) ортосундагы ар кандай өз ара аракеттенүү системалык чакыруулар аркылуу ишке ашырылат. Ошондуктан, программалык камсыздоо бир машинада иштеп, бирок башка машинада иштебегенде, системанын чалууларына байкоо жүргүзүүнүн натыйжаларын карап көрүү жакшы болмок. Тактап айтканда, бул жерде системалык чалуу изи менен талданууга мүмкүн болгон типтүү пункттардын тизмеси:

  • Консолдук киргизүү/чыгаруу
  • Network I/O
  • Файл тутумуна кирүү жана файл киргизүү/чыгаруу
  • Процесс жипинин иштөө мөөнөтүн башкаруу
  • Төмөн деңгээлдеги эс тутумун башкаруу
  • Белгилүү түзмөк драйверлерине кирүү

Качан strace колдонуу керек?

теория боюнча, strace колдонуучу мейкиндигинде каалаган программа менен колдонулат, анткени колдонуучу мейкиндигинде каалаган программа системалык чалууларды жасашы керек. Ал компиляцияланган, төмөнкү деңгээлдеги программалар менен натыйжалуураак иштейт, бирок эгер сиз иштөө убактысынан жана котормочудан кошумча ызы-чууларды жок кыла алсаңыз, Python сыяктуу жогорку деңгээлдеги тилдер менен да иштейт.

Бардык даңкы менен strace бир машинада жакшы иштеген, бирок күтүлбөгөн жерден башка компьютерде иштөөнү токтотуп, файлдар, уруксаттар жөнүндө бүдөмүк билдирүүлөрдү жаратып, же кээ бир буйруктарды же башка нерсени аткарууга ийгиликсиз аракеттерди жасоодо пайда болот... Өкүнүчтүүсү, бирок андай эмес. сертификаттарды текшерүү каталары сыяктуу жогорку деңгээлдеги көйгөйлөр менен жакшы айкалышат. Адатта, бул айкалыштыруу талап кылынат straceкээде ltrace жана жогорку деңгээлдеги куралдар (мисалы, буйрук сабы куралы OpenSSL сертификатты оңдоо үчүн).

Мисал катары биз өз алдынча серверди колдонобуз, бирок тутумдук чалууларды көзөмөлдөө көбүнчө татаалыраак жайылтуу платформаларында жүргүзүлүшү мүмкүн. Сиз жөн гана туура куралдарды тандоо керек.

Жөнөкөй мүчүлүштүктөрдү оңдоо мисалы

Келгиле, сиз foo укмуштуудай сервердик тиркемесин иштеткиңиз келет дейли, жана бул сиз менен аяктайт:

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

Кыязы, ал сиз жазган конфигурация файлын таба алган жок. Бул кээде пакет менеджерлери тиркемени түзгөндө, алар күтүлгөн файл жайгашкан жерлерди жокко чыгаргандыктан болот. Жана эгер сиз бир бөлүштүрүү үчүн орнотуу көрсөтмөсүн аткарсаңыз, башкасында сиз күткөн жерден таптакыр башка файлдарды табасыз. Ката кабары конфигурация файлын кайдан издөө керектигин айтса, көйгөй бир нече секунданын ичинде чечилиши мүмкүн, бирок андай эмес. Ошентип, кайда издөө керек?

Эгер сизде баштапкы кодго мүмкүнчүлүк болсо, аны окуп, баарын биле аласыз. Жакшы резервдик план, бирок эң тез чечим эмес. сыяктуу кадам-кадам оңдоочуга кайрылсаңыз болот gdb жана программанын эмне кылганын көрүңүз, бирок чөйрө менен өз ара аракеттенүүнү көрсөтүү үчүн атайын иштелип чыккан куралды колдонуу алда канча натыйжалуу: strace.

жыйынтыктоо strace ашыкча сезилиши мүмкүн, бирок жакшы кабар, анын көбүн этибарга албай коюуга болот. Из натыйжаларын өзүнчө файлга сактоо үчүн -o операторун колдонуу көбүнчө пайдалуу:

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

Болжол менен чыгаруунун бүт биринчи барагы strace - Бул көбүнчө учурууга төмөнкү деңгээлдеги даярдык. (Көп чалуулар mmap, mpprotec, брк төмөнкү деңгээлдеги эстутумду аныктоо жана динамикалык китепканаларды көрсөтүү сыяктуу нерселер үчүн.) Чындыгында, чыгарууну оңдоо учурунда strace Аягына чейин окуган жакшы. Төмөндө сынак болот жазуу, ката билдирүүсүн көрсөтөт. Биз жогорудан карап, биринчи ката системалык чалуу - чалууну көрөбүз openat, бул ката кетирет ENOENT («файл же каталог табылган жок») ачууга аракет кылуу /etc/foo/config.json. Бул конфигурация файлы болушу керек.

Бул жөн эле мисал болчу, бирок мен колдонгон убакыттын 90% деп айтмакмын strace, мындан алда канча кыйын нерсе жок. Төмөндө толук кадам-кадам мүчүлүштүктөрдү оңдоо колдонмо болуп саналат:

  • Программанын системалык катасы жөнүндө бүдөмүк билдирүүдөн улам капа болуңуз
  • менен программаны кайра баштаңыз strace
  • Издөө натыйжаларынан ката кабарын табыңыз
  • Биринчи ишке ашпай калган тутумдук чалууга жеткенге чейин жогору кетиңиз

4-кадамдагы системалык чалуу эмне туура эмес болгонун ачып берет.

Сунуштар

Сизге татаалыраак мүчүлүштүктөрдү оңдоонун мисалын көрсөтүүдөн мурун, мен сизге натыйжалуу колдонуу үчүн бир нече амалдарды көрсөтөм strace:

адам сенин досуң

Көптөгөн *nix системаларында ядрого системалык чалуулардын толук тизмесин иштетүү аркылуу алууга болот адам сисчайт. сыяктуу нерселерди көрөсүз brk(2), бул чуркап көбүрөөк маалымат алууга болот дегенди билдирет адам 2 брк.

Кичинекей тырмоо: адам 2 айры мага кабык үчүн баракты көрсөтөт айры () в GNU libc, бул, бул чакырууну колдонуу менен ишке ашырылат клон(). Чакыруу семантикасы айры колдонуп программа жазсаңыз ошол бойдон калат айры (), жана из чуркоо - Мен эч кандай чалууларды таппайм айры, алардын ордуна болот клон(). Мындай тырмоолор сизди булакты чыгаруу менен салыштыра баштасаңыз гана чаташтырат strace.

Чыгууну файлга сактоо үчүн -o колдонуңуз

strace кенен өндүрүштү түзө алат, андыктан издөө натыйжаларын өзүнчө файлдарда сактоо көп учурда пайдалуу (жогорку мисалдагыдай). Бул ошондой эле программанын чыгышын чыгаруу менен чаташтырбоо үчүн жардам берет strace консолдо.

Көбүрөөк аргумент дайындарын көрүү үчүн -s колдонуңуз

Ката кабарынын экинчи жарымы жогорудагы мисалда көрсөтүлгөн эмес экенин байкаган чыгарсыз. Себеби strace демейки сап аргументинин биринчи 32 байт гана көрсөтөт. Көбүрөөк көргүңүз келсе, окшош нерсени кошуңуз -s 128 чакырууга strace.

-y файлдарды, розеткаларды ж.б. көзөмөлдөөнү жеңилдетет.

"Баары файл" дегенди билдирет *nix системалары файлга же тармакка же процесстер аралык түтүктөргө тиешелүү болобу, файл дескрипторлорунун жардамы менен бардык киргизүү/чыгаруу иштерин жасайт. Бул программалоо үчүн ыңгайлуу, бирок жалпы көрүнүштөрдү көргөндө чындап эмне болуп жатканын байкоону кыйындатат окуу и жазуу системадагы чалууларды көзөмөлдөө натыйжалары.

Операторду кошуу менен ж, сиз мажбурлайсыз strace чыгаруудагы ар бир файлдын дескрипторуна ал эмнени көрсөтүп жаткандыгы жөнүндө эскертүү менен аннотациялоо.

-p** менен иштеп жаткан процесске тиркеңиз

Төмөндөгү мисалдан көрүнүп тургандай, кээде сиз иштеп жаткан программаны издөөгө туура келет. Эгер ал 1337 процесси катары иштеп жатканы белгилүү болсо (мисалы, чыгаруудан ps), анда сиз аны төмөнкүдөй байкоого болот:

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

Сизге тамыр укуктары керек болушу мүмкүн.

Бала процесстерин көзөмөлдөө үчүн -f колдонуңуз

strace Демейки боюнча, ал бир гана процессти көзөмөлдөйт. Эгер бул процесс бала процесстерин жаратса, анда бала процессин чыгаруу үчүн системалык чакыруу көрүнүп турат, бирок бала процессинин системалык чалуулары көрсөтүлбөйт.

Эгер ката бала процессинде деп ойлосоңуз, билдирүүнү колдонуңуз -f, бул ага байкоо жүргүзүүгө мүмкүндүк берет. Мунун терс жагы - бул чыгаруу сизди ого бетер чаташтырат. Качан strace бир процессти же бир жипти көзөмөлдөйт, ал чалуу окуяларынын бир агымын көрсөтөт. Ал бир эле учурда бир нече процесстерге көз салганда, билдирүү менен үзгүлтүккө учураган чалуунун башталышын көрө аласыз , андан кийин - башка аткаруу бутактары үчүн бир топ чалуулар, андан кийин гана - биринчи аягы <…fookall кайра башталды>. Же оператордун жардамы менен бардык издердин натыйжаларын ар кандай файлдарга бөлүңүз -ff (толук маалымат лидерлик боюнча strace).

Издерди чыпкалоо -e

Көрүнүп тургандай, издин натыйжасы бардык мүмкүн болгон системалык чалуулардын чыныгы үймөгү болуп саналат. Желек -e Изди чыпкалай аласыз (караңыз жетекчилик боюнча strace). Негизги артыкчылыгы - чыпкаланган изди иштетүү, андан кийин толук из салууга караганда тезирээк талаасынын` at. Чынын айтсам, мен дээрлик дайыма маани бербейм.

Бардык каталар жаман эмес

Жөнөкөй жана кеңири таралган мисал, бир эле учурда бир нече жерден файлды издеген программа, мисалы, аткарылуучу файлды камтыган каталогду издеген кабык:

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

"Ката жөнүндө кабарлоодон мурун акыркы аткарылбай калган суроо" сыяктуу эвристикалар тиешелүү каталарды табууда жакшы. Кандай болбосун, эң аягынан баштоо логикалык.

C программалоо боюнча окуу куралдары системалык чалууларды түшүнүүгө жардам берет.

C китепканаларына стандарттуу чалуулар системалык чалуулар эмес, жука беттик катмар гана. Ошентип, эгер сиз C тилинде кантип жана эмне кылуу керектигин бир аз түшүнсөңүз, анда системалык чалуу изинин натыйжаларын түшүнүү оңой болот. Мисалы, сизде тармактык системаларга чалууларды оңдоодо көйгөй бар, ошол эле классиканы караңыз Тармактык программалоо боюнча Bija колдонмосу.

Бир кыйла татаал мүчүлүштүктөрдү оңдоо мисалы

Жөнөкөй мүчүлүштүктөрдү оңдоонун мисалы мен иштегенде көбүнчө эмне менен алектенишим керектигин айттым strace. Бирок, кээде чыныгы иликтөө талап кылынат, андыктан бул жерде өркүндөтүлгөн мүчүлүштүктөрдү оңдоонун реалдуу турмуштук мисалы келтирилген.

bcron - тапшырманы иштетүү пландоочусу, * nix демонунун дагы бир ишке ашырылышы Мурунку. Ал серверде орнотулган, бирок кимдир бирөө графикти түзөтүүгө аракет кылганда, мындай болот:

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

Макул, бул дегенди билдирет bcron белгилүү бир файлды жазууга аракет кылды, бирок ал ишке ашкан жок жана ал эмне үчүн экенин моюнга албайт. ачуу 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 +++

Аягына жакын ката кабары бар жазуу, бирок бул жолу бир нерсе башкача. Биринчиден, адатта буга чейин пайда болгон тиешелүү системалык чалуу катасы жок. Экинчиден, кимдир бирөө мурунтан эле ката билдирүүсүн окуп чыкканы көрүнүп турат. Бул чыныгы көйгөй башка жерде окшойт, жана bcrontab жөн гана билдирүүнү кайра ойнойт.

Эгерде сиз карасаңыз адам 2 оку, сиз биринчи аргумент (3) файл дескриптору экенин көрө аласыз, аны * nix бардык киргизүү/чыгаруу процесстери үчүн колдонот. Дескриптор 3 кайсы файлды билдирерин кантип билсем болот? Бул учурда, сиз чуркай аласыз strace оператор менен ж (жогоруда караңыз) жана ал сизге автоматтык түрдө айтып берет, бирок ушуга окшогон нерселерди аныктоо үчүн, изин натыйжаларын кантип окуп жана талдоо керектигин билүү пайдалуу.

Файлдын дескрипторунун булагы көптөгөн системалык чалуулардын бири болушу мүмкүн (баары дескриптор эмне үчүн экенине жараша болот - консол, тармак розеткасы, файлдын өзү же башка нерсе), бирок кандай болсо да, биз издейбиз 3 кайтаруу менен чалуулар (б.а. биз издөө натыйжаларында “= 3” издейбиз). Бул натыйжада алардын 2си бар: openat эң жогорку жана чанак ортосунда. openat файлды ачат, бирок жакын(3) андан кийин кайра жабылганын көрсөтөт. (Rake: файлдын дескрипторлору ачылганда жана жабылганда кайра колдонулушу мүмкүн). Чалуу розетка () ылайыктуу, анткени ал мурунку акыркысы окуу (), жана bcrontab розетка аркылуу бир нерсе менен иштейт экен. Кийинки сап файлдын дескриптору менен байланышкандыгын көрсөтөт unix домендик розетка жолдон /var/run/bcron-spool.

Демек, биз менен байланышкан жараянды табышыбыз керек unix розетка башка жагынан. Бул максат үчүн бир нече тыкан трюктар бар, алардын экөө тең серверди жайгаштырууларды оңдоо үчүн пайдалуу. Биринчи колдонуу болуп саналат netstat же жаңыраак ss (розетка абалы). Эки команда тең системанын активдүү тармактык байланыштарын көрсөтүп, билдирүүнү кабыл алат -l угуу розеткаларын, ошондой эле операторду сүрөттөө үчүн -p розеткага туташкан программаларды кардар катары көрсөтүү үчүн. (Дагы көптөгөн пайдалуу варианттар бар, бирок бул экөө бул тапшырма үчүн жетиштүү.)

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

Бул угуучунун буйрук экенин көрсөтүп турат inixserver, процесс ID 20629 менен иштейт. (Жана кокустан, ал розетка катары 3 файл дескрипторун колдонот.)

Ошол эле маалыматты табуу үчүн экинчи чындап пайдалуу курал деп аталат lsof. Ал системадагы бардык ачык файлдарды (же файлдын дескрипторлорун) тизмелейт. Же бир белгилүү файл жөнүндө маалымат ала аласыз:

# 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

Процесс 20629 - бул узак мөөнөттүү сервер, андыктан аны тиркөөгө болот strace сыяктуу нерсени колдонуу strace -o /tmp/trace -p 20629. Эгер сиз башка терминалда cron тапшырмасын түзөтсөңүз, сиз ката менен из чыгарууну аласыз. Жана бул жерде жыйынтык:

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

(Акыркы кабыл алуу () издөөдө аягына чыкпайт.) Дагы, тилекке каршы, бул жыйынтык биз издеп жаткан катаны камтыбайт. Биз bcrontag розеткага жөнөткөн же розеткадан кабыл алган билдирүүлөрдү көрбөйбүз. Анын ордуна, процессти толук башкаруу (клон, күтө 4, SIGCHLD ж.б.) Бул процесс, сиз ойлогондой, чыныгы ишти аткарган бала процессин жаратат. Эгер сиз анын изин кармашыңыз керек болсо, чалууга кошуңуз strace -f. Бул жаңы натыйжада ката кабарын издегенибизде табабыз -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 +++

Эми бул бир нерсе. 21470 процесси жолдо файл түзүүгө аракет кылып жатканда "кирүү четке кагылды" катасын алат tmp/spool.21470.1573692319.854640 (учурдагы жумушчу каталогуна тиешелүү). Эгерде биз учурдагы жумушчу каталогду билсек, анда биз дагы толук жолду билебиз жана процесс эмне үчүн анда убактылуу файлды түзө албастыгын түшүнө алабыз. Тилекке каршы, процесс мурунтан эле чыгып кеткен, андыктан жөн эле колдоно албайсыз lsof -p 21470 учурдагы каталогду табуу үчүн, бирок сиз карама-каршы багытта иштей аласыз - каталогду өзгөрткөн PID 21470 тутумдук чалууларды издеңиз. (Эгер андайлар жок болсо, PID 21470 аларды ата-энесинен мурастап алган болушу керек жана бул мурунтан эле lsof -б табуу мүмкүн эмес.) Бул система чалуу болуп саналат чдир (Заманбап онлайн издөө системаларынын жардамы менен табуу оңой). Бул жерде 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 +++

(Эгер адашып калсаңыз, менин мурунку постумду окугуңуз келет жөнүндө *nix процесстерин башкаруу жана кабыктар.) Ошентип, PID 20629 сервери жолдо файлды түзүүгө уруксат алган жок /var/spool/cron/tmp/spool.21470.1573692319.854640. Кыязы, мунун себеби классикалык файл тутумунун уруксат орнотуулары. текшерип көрөлү:

# 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

Ит ошол жерге көмүлгөн! Сервер колдонуучу cron катары иштейт, бирок каталогго жазууга root гана уруксаты бар /var/spool/cron/tmp/. Жөнөкөй буйрук chown cron /var/spool/cron/tmp/ мажбурлайт bcron туура иштөө. (Эгерде көйгөй бул болбосо, анда кийинки эң шектүү SELinux же AppArmor сыяктуу ядронун коопсуздук модулу, андыктан ядро ​​​​билдирүү журналын текшерет элем. dmesg.)

жалпы

Системалык чалуулардын издери башталгыч үчүн өтө оор болушу мүмкүн, бирок мен алар жалпы жайылтуу көйгөйлөрүнүн бүтүндөй классын оңдоонун тез жолу экенин көрсөттүм деп үмүттөнөм. Көп процессти оңдоого аракет кылып жатканын элестетиңиз bcronэтап-этабы менен мүчүлүштүктөрдү колдонуу.

Системалык чалуу тизмеги боюнча натыйжаларды артка карай талдоо чеберчиликти талап кылат, бирок мен айткандай, дээрлик ар дайым колдонуу strace, Мен жөн гана из натыйжасын алып, каталарды аягынан баштап издейм. Кандай болгон күндө да, strace мүчүлүштүктөрдү оңдоого көп убакытты үнөмдөөгө жардам берет. Сизге да пайдалуу болот деп ишенем.

Source: www.habr.com

Комментарий кошуу