ස්ට්‍රේස් සමඟ මෘදුකාංග යෙදවීම නිදොස් කිරීම

ස්ට්‍රේස් සමඟ මෘදුකාංග යෙදවීම නිදොස් කිරීම

මගේ දවසේ රැකියාව බොහෝ දුරට මෘදුකාංග යෙදවීමයි, එයින් අදහස් කරන්නේ මම මෙවැනි ප්‍රශ්නවලට පිළිතුරු දීමට බොහෝ කාලයක් ගත කරන බවයි:

  • මෙම මෘදුකාංගය සංවර්ධකයා සඳහා ක්‍රියා කරයි, නමුත් මට නොවේ. ඇයි?
  • ඊයේ මෙම මෘදුකාංගය මා වෙනුවෙන් වැඩ කළ නමුත් අද එය එසේ නොවේ. ඇයි?

මෙය සාමාන්‍ය මෘදුකාංග නිදොස්කරණයට වඩා තරමක් වෙනස් දෝශ නිරාකරණයකි. නිතිපතා නිදොස්කරණය යනු කේතයේ තර්කනයයි, නමුත් යෙදවුම් නිදොස්කරණය යනු කේතය සහ පරිසරය අතර අන්තර්ක්‍රියාවයි. ගැටලුවේ මුල තාර්කික දෝෂයක් වුවද, සියල්ල ක්‍රියා කරන්නේ එක් යන්ත්‍රයක මිස තවත් යන්ත්‍රයකින් නොවේ යන්නෙන් අදහස් වන්නේ ගැටලුව කෙසේ හෝ පරිසරයේ පවතින බවයි.

ඒ නිසා සුපුරුදු debugging tools වෙනුවට gdb නිදොස්කරණය යෙදවීම සඳහා මා සතුව වෙනස් මෙවලම් කට්ටලයක් තිබේ. සහ "මෙම මෘදුකාංගය මට වැඩ නොකරන්නේ ඇයි?" වැනි ගැටලුව සමඟ කටයුතු කිරීම සඳහා මගේ ප්‍රියතම මෙවලම. කියලා තීරය.

ස්ට්රේස් යනු කුමක්ද?

තීරය "පද්ධති ඇමතුම් ලුහුබැඳීම" සඳහා මෙවලමකි. එය මුලින් ලිනක්ස් සඳහා නිර්මාණය කරන ලද්දකි, නමුත් වෙනත් පද්ධති සඳහා මෙවලම් සමඟ එකම නිදොස් කිරීමේ උපක්‍රම සිදු කළ හැකිය (ඩීට්රේස් හෝ ktration).

මූලික යෙදුම ඉතා සරල ය. ඔබට ඕනෑම විධානයක් සමඟ ස්ට්‍රේස් ධාවනය කිරීමට අවශ්‍ය වන අතර එය සියලුම පද්ධති ඇමතුම් ඉවත දමනු ඇත (මුලින්ම ඔබට එය ස්ථාපනය කිරීමට සිදුවනු ඇත. තීරය):

$ 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 සම්මත පුස්තකාලයේ ක්‍රියාකාරී ඇමතුමක් ඇත ලියන්න (), පද්ධති ඇමතුම සඳහා සියලු ගෘහ නිර්මාණ-විශේෂිත කේතය අඩංගු වේ ලියන්න.

ස්ට්‍රේස් සමඟ මෘදුකාංග යෙදවීම නිදොස් කිරීම

කෙටියෙන් කිවහොත්, යෙදුමක් සහ එහි පරිසරය (පරිගණක පද්ධති) අතර ඕනෑම අන්තර්ක්‍රියාවක් පද්ධති ඇමතුම් හරහා සිදු කෙරේ. ඒ නිසා Software එක එක Machine එකක වැඩ කරනකොට තව machine එකක වැඩ කරනකොට system call tracing results දිහා බැලුවොත් හොදයි. වඩාත් නිශ්චිතව, පද්ධති ඇමතුම් හෝඩුවාවක් භාවිතයෙන් විශ්ලේෂණය කළ හැකි සාමාන්‍ය ලක්ෂ්‍ය ලැයිස්තුවක් මෙන්න:

  • කොන්සෝලය I/O
  • ජාල I/O
  • ගොනු පද්ධති ප්රවේශය සහ ගොනු I/O
  • ක්‍රියාවලි ත්‍රෙඩ් එකක ආයු කාලය කළමනාකරණය කිරීම
  • අඩු මට්ටමේ මතක කළමනාකරණය
  • විශේෂිත උපාංග ධාවක වෙත ප්රවේශය

ස්ට්රේස් භාවිතා කළ යුත්තේ කවදාද?

න්යාය තුල, තීරය පරිශීලක අවකාශයේ ඕනෑම වැඩසටහනක් සමඟ භාවිතා කරයි, මන්ද පරිශීලක අවකාශයේ ඕනෑම වැඩසටහනක් පද්ධති ඇමතුම් කළ යුතුය. එය සම්පාදනය කරන ලද, පහත් මට්ටමේ වැඩසටහන් සමඟ වඩාත් කාර්යක්ෂමව ක්‍රියා කරයි, නමුත් ඔබට ධාවන කාලය සහ පරිවර්තකයේ අමතර ශබ්දය කපා හැරිය හැකි නම් එය Python වැනි ඉහළ මට්ටමේ භාෂා සමඟද ක්‍රියා කරයි.

එහි සියලු මහිමයෙන් තීරය එක් යන්ත්‍රයක හොඳින් ක්‍රියා කරන මෘදුකාංග දෝශ නිරාකරණය කිරීමේදී එය ප්‍රකාශ වේ, නමුත් හදිසියේම තවත් යන්ත්‍රයක ක්‍රියා කිරීම නවත්වයි, ලිපිගොනු, අවසරයන් හෝ සමහර විධාන හෝ වෙනත් දෙයක් ක්‍රියාත්මක කිරීමට අසාර්ථක උත්සාහයන් පිළිබඳ නොපැහැදිලි පණිවිඩ නිකුත් කරයි... එය කණගාටුවට කරුණකි, නමුත් එය එසේ නොවේ. සහතික සත්‍යාපන දෝෂ වැනි ඉහළ මට්ටමේ ගැටලු සමඟ හොඳින් ඒකාබද්ධ වේ. සාමාන්යයෙන් මෙය සංයෝජනයක් අවශ්ය වේ තීරයසමහර විට සොයා ගැනීම සහ ඉහළ මට්ටමේ මෙවලම් (විධාන රේඛා මෙවලම වැනි openssl සහතිකය නිදොස් කිරීමට).

අපි උදාහරණයක් ලෙස ස්වාධීන සේවාදායකයක් භාවිතා කරන්නෙමු, නමුත් පද්ධති ඇමතුම් ලුහුබැඳීම බොහෝ විට වඩාත් සංකීර්ණ යෙදවුම් වේදිකාවල සිදු කළ හැක. ඔබට අවශ්‍ය වන්නේ නිවැරදි මෙවලම් තෝරා ගැනීම පමණි.

සරල දෝශ නිරාකරණ උදාහරණය

ඔබට විශ්මයජනක සේවාදායක යෙදුම් foo ධාවනය කිරීමට අවශ්‍ය යැයි කියමු, සහ ඔබ අවසන් වන්නේ මෙයයි:

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

පෙනෙන විදිහට එයට ඔබ ලියූ වින්‍යාස ගොනුව සොයාගත නොහැකි විය. මෙය සිදුවන්නේ සමහර විට පැකේජ කළමනාකරුවන් යෙදුමක් සම්පාදනය කරන විට, ඔවුන් අපේක්ෂිත ගොනු ස්ථාන අභිබවා යන බැවිනි. තවද ඔබ එක් බෙදාහැරීමක් සඳහා ස්ථාපන මාර්ගෝපදේශය අනුගමනය කරන්නේ නම්, තවත් බෙදාහැරීමකදී ඔබ බලාපොරොත්තු වූ ස්ථානයට වඩා සම්පූර්ණයෙන්ම වෙනස් ගොනු සොයා ගනී. දෝෂ පණිවිඩයේ වින්‍යාස ගොනුව සොයන්නේ කොතැනදැයි පැවසුවහොත් ගැටළුව තත්පර කිහිපයකින් විසඳිය හැකි නමුත් එය එසේ නොවේ. ඉතින් කොහෙද බලන්න?

ඔබට ප්‍රභව කේතයට ප්‍රවේශය තිබේ නම්, ඔබට එය කියවා සියල්ල සොයා ගත හැක. හොඳ උපස්ථ සැලැස්මක්, නමුත් වේගවත්ම විසඳුම නොවේ. ඔබට වැනි පියවරෙන් පියවර නිදොස්කරණයක් වෙත යොමු විය හැක gdb සහ වැඩසටහන කරන්නේ කුමක්දැයි බලන්න, නමුත් පරිසරය සමඟ අන්තර්ක්‍රියා පෙන්වීමට විශේෂයෙන් නිර්මාණය කර ඇති මෙවලමක් භාවිතා කිරීම වඩාත් ඵලදායී වේ: තීරය.

නිගමනය තීරය අතිරික්ත බවක් පෙනෙන්නට ඇත, නමුත් ශුභාරංචිය නම් එයින් බොහොමයක් ආරක්ෂිතව නොසලකා හැරිය හැකි බවයි. ලුහුබැඳීමේ ප්‍රතිඵල වෙනම ගොනුවකට සුරැකීමට -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 +++

ප්‍රතිදානයේ සම්පූර්ණ පළමු පිටුව ආසන්න වශයෙන් තීරය - මෙය සාමාන්යයෙන් දියත් කිරීම සඳහා පහත් මට්ටමේ සූදානමකි. (ඇමතුම් ගොඩක් mmap, ආරක්ෂා කරනවා, quill අඩු මට්ටමේ මතකය හඳුනා ගැනීම සහ ගතික පුස්තකාල ප්‍රදර්ශනය කිරීම වැනි දේ සඳහා.) ඇත්ත වශයෙන්ම, ප්‍රතිදානය දෝෂහරණය කිරීමේදී තීරය අග සිට කියවීම වඩා හොඳය. පහත අභියෝගයක් වනු ඇත ලියන්න, එය දෝෂ පණිවිඩයක් පෙන්වයි. අපි ඉහළින් බලන අතර පළමු වැරදි පද්ධති ඇමතුම දකිනවා - ඇමතුම openat, එය දෝෂයක් ඇති කරයි ENOENT ("ගොනුව හෝ නාමාවලිය හමු නොවීය") විවෘත කිරීමට උත්සාහ කරයි /etc/foo/config.json. වින්‍යාස ගොනුව තිබිය යුත්තේ මෙයයි.

මෙය උදාහරණයක් පමණි, නමුත් මම භාවිතා කරන වේලාවෙන් 90% ක් කියමි තීරය, මේකට වඩා කරන්න අමාරු දෙයක් නෑ. පහත දැක්වෙන්නේ සම්පූර්ණ පියවරෙන් පියවර දෝෂහරණ මාර්ගෝපදේශයකි:

  • වැඩසටහනකින් system-y දෝෂයක් ගැන නොපැහැදිලි පණිවිඩයක් නිසා කලබල වන්න
  • සමඟ වැඩසටහන නැවත ආරම්භ කරන්න තීරය
  • ලුහුබැඳීමේ ප්‍රතිඵලවල දෝෂ පණිවිඩය සොයන්න
  • ඔබ පළමු අසාර්ථක පද්ධති ඇමතුමට පහර දෙන තෙක් ඉහළට යන්න

4 වන පියවරේ ඇති පද්ධති ඇමතුම වැරදි වූ දේ හෙළි කිරීමට බොහෝ දුරට ඉඩ ඇත.

ඉඟි

වඩාත් සංකීර්ණ නිදොස්කරණය පිළිබඳ උදාහරණයක් ඔබට පෙන්වීමට පෙර, ඵලදායී භාවිතය සඳහා මම ඔබට උපක්‍රම කිහිපයක් පෙන්වන්නම් තීරය:

මිනිසා ඔබේ මිතුරා ය

බොහෝ *nix පද්ධතිවල, කර්නලය වෙත ලැබෙන පද්ධති ඇමතුම් සම්පූර්ණ ලැයිස්තුවක් ධාවනය කිරීමෙන් ලබාගත හැක මිනිසා syscalls. වැනි දේවල් ඔබට පෙනෙනු ඇත brk(2), එනම් ධාවනය කිරීමෙන් වැඩි විස්තර ලබා ගත හැක මිනිසා 2 brk.

කුඩා රාක්කය: මිනිසා 2 දෙබලක මට shell එක සඳහා පිටුව පෙන්වයි දෙබලක () в GNU libc, එය හැරෙන්නේ, ඇමතුම භාවිතයෙන් ක්රියාත්මක වේ ක්ලෝන (). අර්ථ ශාස්ත්‍රය අමතන්න දෙබස් ඔබ භාවිතා කරමින් වැඩසටහනක් ලියන්නේ නම් එලෙසම පවතී දෙබලක (), සහ හෝඩුවාවක් ධාවනය කරන්න - මට ඇමතුම් කිසිවක් සොයාගත නොහැක දෙබස්, ඔවුන් වෙනුවට පවතිනු ඇත ක්ලෝන (). ඔබ ප්‍රභවය ප්‍රතිදානය සමඟ සංසන්දනය කිරීමට පටන් ගන්නේ නම් එවැනි රේක් ඔබව ව්‍යාකූල කරයි තීරය.

ප්‍රතිදානය ගොනුවකට සුරැකීමට -o භාවිතා කරන්න

තීරය විස්තීර්ණ ප්‍රතිදානයක් ජනනය කළ හැක, එබැවින් ලුහුබැඳීමේ ප්‍රතිඵල වෙනම ගොනු වල ගබඩා කිරීම බොහෝ විට ප්‍රයෝජනවත් වේ (ඉහත උදාහරණයේ දී මෙන්). මෙය ප්‍රතිදානය සමඟ වැඩසටහන් ප්‍රතිදානය ව්‍යාකූල වීම වළක්වා ගැනීමට ද උපකාරී වේ තීරය කොන්සෝලය තුළ.

තවත් තර්ක දත්ත බැලීමට -s භාවිතා කරන්න

ඉහත උදාහරණ සටහනේ දෝෂ පණිවිඩයේ දෙවන භාගය නොපෙන්වන බව ඔබ දැක ඇති. ඒක නිසා තීරය පෙරනිමියෙන් පෙන්වන්නේ තන්තු තර්කයේ පළමු බයිට් 32 පමණි. ඔබට තවත් බැලීමට අවශ්‍ය නම්, එවැනි දෙයක් එක් කරන්න -s 128 ඇමතුමට තීරය.

-y ගොනු, සොකට් ආදිය නිරීක්ෂණය කිරීම පහසු කරයි.

"සියල්ලම ගොනුවකි" යන්නෙන් අදහස් වන්නේ *nix පද්ධති මඟින් සියලුම I/O ගොනු විස්තර භාවිතා කරන බවයි, එය ගොනුවකට හෝ ජාලයකට හෝ අන්තර් ක්‍රියාවලි පයිප්පවලට අදාළ වේ. මෙය ක්‍රමලේඛනය සඳහා පහසු වේ, නමුත් ඔබ පොදුවේ දකින විට ඇත්ත වශයෙන්ම සිදුවන්නේ කුමක්ද යන්න නිරීක්ෂණය කිරීම අපහසු කරයි කියවන්න и ලියන්න පද්ධතියේ ඇමතුම් ලුහුබැඳීමේ ප්රතිඵල තුළ.

ක්රියාකරු එකතු කිරීමෙනි -y, ඔබ බල කරනු ඇත තීරය ප්‍රතිදානයේ ඇති සෑම ගොනු විස්තරයක්ම එය පෙන්වා දෙන දේ පිළිබඳ සටහනක් සමඟින් සටහන් කරන්න.

-p** සමඟ දැනටමත් ක්‍රියාත්මක වන ක්‍රියාවලියකට අමුණන්න

පහත උදාහරණයෙන් ඔබට පෙනෙන පරිදි, සමහර විට ඔබට දැනටමත් ක්රියාත්මක වන වැඩසටහනක් සොයා ගැනීමට අවශ්ය වේ. එය ක්‍රියාවලිය 1337 ලෙස ක්‍රියාත්මක වන බව දන්නේ නම් (කියන්න, ප්‍රතිදානයෙන් ps), එවිට ඔබට එය මෙලෙස සොයා ගත හැක:

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

ඔබට මූල අයිතිවාසිකම් අවශ්‍ය විය හැකිය.

ළමා ක්රියාවලීන් නිරීක්ෂණය කිරීමට -f භාවිතා කරන්න

තීරය පෙරනිමියෙන්, එය එක් ක්‍රියාවලියක් පමණක් හඹා යයි. මෙම ක්‍රියාවලිය ළමා ක්‍රියාවලීන් බිහි කරන්නේ නම්, ළමා ක්‍රියාවලිය බිහි කිරීමට පද්ධති ඇමතුම දැකිය හැකි නමුත්, ළමා ක්‍රියාවලියේ පද්ධති ඇමතුම් දර්ශනය නොවේ.

දෝෂය ළමා ක්‍රියාවලියක යැයි ඔබ සිතන්නේ නම්, ප්‍රකාශය භාවිතා කරන්න -f, මෙය එහි ලුහුබැඳීම සක්‍රීය කරයි. මෙහි ඇති අවාසිය නම් ප්‍රතිදානය ඔබව තවත් ව්‍යාකූල කිරීමයි. කවදා ද තීරය එක් ක්‍රියාවලියක් හෝ එක් නූල් එකක් ලුහුබඳියි, එය ඇමතුම් සිදුවීම්වල තනි ප්‍රවාහයක් පෙන්වයි. එය එකවර ක්‍රියාවලි කිහිපයක් ලුහුබැඳ ගිය විට, පණිවිඩයක් මඟින් ඇමතුමක ආරම්භය බාධා වන බව ඔබට පෙනෙනු ඇත , පසුව - අනෙකුත් ක්රියාත්මක කිරීමේ ශාඛා සඳහා ඇමතුම් පොකුරක්, සහ පසුව පමණක් - පළමු එකේ අවසානය <...foocall නැවත ආරම්භ විය>. නැතහොත් ක්‍රියාකරු භාවිතා කරමින් සියලුම හෝඩුවාවන් ප්‍රතිඵල විවිධ ගොනුවලට බෙදන්න -ff (විස්තර තුළ නායකත්වය මත තීරය).

-e භාවිතා කරමින් හෝඩුවාවන් පෙරන්න

ඔබට පෙනෙන පරිදි, ලුහුබැඳීමේ ප්රතිඵලය හැකි සියලු පද්ධති ඇමතුම්වල සැබෑ ගොඩවල් වේ. ධජ -e ඔබට හෝඩුවාවක් පෙරීමට හැකිය (බලන්න නායකත්වය මත තීරය) ප්‍රධාන වාසිය නම් ෆිල්ටර් කළ ට්‍රේස් එකක් ෆුල් ට්‍රේස් එකක් කරනවාට වඩා වේගවත් වීමයි grep`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 වලදී කොහොමද සහ මොනවද කරන්නේ කියලා පොඩ්ඩක්වත් තේරුම් ගත්තොත් system call trace එකේ ප්‍රතිඵල තේරුම් ගන්න ලේසියි. උදාහරණයක් ලෙස, ඔබට ජාල පද්ධති වෙත ඇමතුම් දෝෂහරණය කිරීමේ ගැටලුවක් තිබේ, එම සම්භාව්‍ය දෙස බලන්න ජාල වැඩසටහන්කරණය සඳහා Bija's Guide.

වඩාත් සංකීර්ණ නිදොස් කිරීමේ උදාහරණයක්

මම දැනටමත් පවසා ඇත්තේ සරල නිදොස්කරණයේ උදාහරණය මා සමඟ වැඩ කිරීමේදී වැඩිපුරම ගනුදෙනු කිරීමට ඇති උදාහරණයකි තීරය. කෙසේ වෙතත්, සමහර විට සැබෑ පරීක්ෂණයක් අවශ්‍ය වේ, එබැවින් වඩාත් දියුණු නිදොස්කරණයේ සැබෑ ජීවිතය පිළිබඳ උදාහරණයක් මෙන්න.

bcron - කාර්ය සැකසුම් කාලසටහන, *nix ඩීමන් තවත් ක්‍රියාත්මක කිරීමක් cron වලින්. එය සේවාදායකයේ ස්ථාපනය කර ඇත, නමුත් යමෙකු කාලසටහන සංස්කරණය කිරීමට උත්සාහ කරන විට, මෙය සිදු වේ:

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

හරි, ඒ කියන්නේ bcron කිසියම් ගොනුවක් ලිවීමට උත්සාහ කළ නමුත් එය සාර්ථක වූයේ නැත, ඔහු එයට හේතුව පිළිගන්නේ නැත. හෙළිදරව් කිරීම තීරය:

# 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 සියලු I/O සැකසුම් සඳහා භාවිතා කරයි. ගොනු විස්තරය 3 නියෝජනය කරන්නේ කුමක්දැයි සොයා ගන්නේ කෙසේද? මෙම විශේෂිත අවස්ථාවෙහිදී, ඔබට ධාවනය කළ හැකිය තීරය ක්රියාකරු සමඟ -y (ඉහත බලන්න) සහ එය ස්වයංක්‍රීයව ඔබට කියනු ඇත, නමුත් මෙවැනි දේවල් සොයා ගැනීමට, ප්‍රතිඵල ලුහුබැඳීම සහ විග්‍රහ කරන්නේ කෙසේදැයි දැන ගැනීම ප්‍රයෝජනවත් වේ.

ගොනු විස්තරයක ප්‍රභවය බොහෝ පද්ධති ඇමතුම් වලින් එකක් විය හැකිය (ඒ සියල්ල විස්තරකය කුමක් සඳහාද යන්න මත රඳා පවතී - කොන්සෝලයක්, ජාල සොකට් එකක්, ගොනුව හෝ වෙනත් දෙයක්), නමුත් එය එසේ වේවා, අපි සොයන්නෙමු 3 ආපසු ලබා දීමෙන් ඇමතුම් (එනම් අපි සොයාගැනීමේ ප්‍රතිඵලවල "= 3" සොයන්නෙමු). මෙම ප්රතිඵලයේ ඒවායින් 2 ක් ඇත: openat ඉතා ඉහලින් සහ තව්ව අතරමැද දී. openat ගොනුව විවෘත කරයි නමුත් සමීප(3) එවිට එය නැවත වැසෙන බව පෙන්වයි. (Rake: file descriptors විවෘත කර වසා දැමූ විට නැවත භාවිතා කළ හැක). අමතන්න තව්ව() එය පෙර අවසන් එක නිසා සුදුසුයි කියවන්න(), සහ 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 -o /tmp/trace -p 20629. ඔබ වෙනත් පර්යන්තයක ක්‍රෝන් කාර්යයක් සංස්කරණය කරන්නේ නම්, ඔබට දෝෂයක් සහිත ට්‍රේස් ප්‍රතිදානයක් ලැබෙනු ඇත. සහ මෙහි ප්රතිඵලය:

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. අලුත් ප්‍රතිඵලයේ ඇති Error Message එක 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 +++

දැන්, ඒක දෙයක්. 21470 ක්‍රියාවලියට "ප්‍රවේශය ප්‍රතික්ෂේප කරන ලද" දෝෂයක් මාර්ගයේදී ගොනුවක් සෑදීමට උත්සාහ කරන විට ලැබේ tmp/spool.21470.1573692319.854640 (වත්මන් වැඩ කරන නාමාවලිය සම්බන්ධ). අපි දැනට ක්‍රියාත්මක වන නාමාවලිය දැන සිටියේ නම්, අපි සම්පූර්ණ මාර්ගය ද දන්නා අතර ක්‍රියාවලියට එහි තාවකාලික ගොනුව සෑදිය නොහැක්කේ මන්දැයි සොයා ගැනීමට හැකි වනු ඇත. අවාසනාවකට, ක්‍රියාවලිය දැනටමත් පිටවී ඇත, එබැවින් ඔබට පමණක් භාවිතා කළ නොහැක lsof -p 21470 වත්මන් නාමාවලිය සොයා ගැනීම සඳහා, නමුත් ඔබට ප්රතිවිරුද්ධ දිශාවට වැඩ කළ හැකිය - නාමාවලිය වෙනස් කරන PID 21470 පද්ධති ඇමතුම් සඳහා බලන්න. (කිසිවක් නොමැති නම්, PID 21470 ඒවා එහි මාපියන්ගෙන් උරුම වී තිබිය යුතු අතර, මෙය දැනටමත් සිදු කර ඇත. lsof -p සොයාගත නොහැක.) මෙම පද්ධති ඇමතුම වේ chdir (නවීන ඔන්ලයින් සෙවුම් යන්ත්‍ර ආධාරයෙන් සොයා ගැනීමට පහසු වේ). සහ 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

එතන තමයි බල්ලව වළලන්නේ! සේවාදායකය පරිශීලක ක්‍රෝන් එකක් ලෙස ක්‍රියා කරයි, නමුත් නාමාවලියට ලිවීමට අවසර ඇත්තේ root පමණි /var/spool/cron/tmp/. සරල විධානය chown cron /var/spool/cron/tmp/ බල කරනු ඇත bcron නිවැරදිව වැඩ කරන්න. (ප්‍රශ්නය එය නොවේ නම්, ඊළඟට සැක කළ හැකි සැකකරු SELinux හෝ AppArmor වැනි කර්නල් ආරක්ෂණ මොඩියුලයක් වේ, එබැවින් මම කර්නල් පණිවිඩ ලොගය පරීක්ෂා කරමි. dmesg.)

එකතුව

පද්ධති ඇමතුම් ලුහුබැඳීම් ආධුනිකයෙකුට අතිමහත් විය හැක, නමුත් මම ඒවා පොදු යෙදවීමේ ගැටළු සම්පූර්ණ පන්තියක් නිදොස් කිරීමට ඉක්මන් ක්‍රමයක් බව පෙන්වා දී ඇතැයි මම බලාපොරොත්තු වෙමි. බහු ක්‍රියාවලියක් නිදොස් කිරීමට උත්සාහ කරන බව සිතන්න bcronපියවරෙන් පියවර නිදොස්කරණයක් භාවිතා කරමින්.

පද්ධති ඇමතුම් දාමයක් ඔස්සේ ලුහුබැඳීමේ ප්‍රතිඵල පසුපසට විග්‍රහ කිරීමට කුසලතා අවශ්‍ය වේ, නමුත් මම කී පරිදි, සෑම විටම පාහේ, භාවිතා කරමින් තීරය, මම ලුහුබැඳීමේ ප්‍රතිඵලය ලබා ගන්නා අතර අවසානයේ සිට ආරම්භ වන දෝෂ සොයමි. කෙසේ හෝ, තීරය නිදොස්කරණයේදී බොහෝ කාලයක් ඉතිරි කර ගැනීමට මට උපකාර කරයි. එය ඔබටත් ප්‍රයෝජනවත් වේ යැයි සිතමි.

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න