ஸ்ட்ரேஸ் மூலம் மென்பொருள் வரிசைப்படுத்தல் பிழைத்திருத்தம்

ஸ்ட்ரேஸ் மூலம் மென்பொருள் வரிசைப்படுத்தல் பிழைத்திருத்தம்

எனது நாள் வேலை பெரும்பாலும் மென்பொருள் வரிசைப்படுத்தல் ஆகும், அதாவது இதுபோன்ற கேள்விகளுக்கு பதிலளிக்க நான் நிறைய நேரம் செலவிடுகிறேன்:

  • இந்த மென்பொருள் டெவலப்பருக்கு வேலை செய்கிறது, ஆனால் எனக்கு அல்ல. ஏன்?
  • நேற்று இந்த மென்பொருள் எனக்கு வேலை செய்தது, ஆனால் இன்று அது இல்லை. ஏன்?

இது ஒரு வகையான பிழைத்திருத்தமாகும், இது வழக்கமான மென்பொருள் பிழைத்திருத்தத்திலிருந்து சற்று வித்தியாசமானது. வழக்கமான பிழைத்திருத்தம் என்பது குறியீட்டின் தர்க்கத்தைப் பற்றியது, ஆனால் வரிசைப்படுத்தல் பிழைத்திருத்தம் என்பது குறியீட்டிற்கும் சூழலுக்கும் இடையிலான தொடர்பு பற்றியது. பிரச்சனையின் வேர் தர்க்கப் பிழையாக இருந்தாலும், எல்லாமே ஒரு இயந்திரத்தில் வேலை செய்யாமல் மற்றொன்றில் இயங்குவதால், பிரச்சனை எப்படியோ சூழலில் உள்ளது என்று அர்த்தம்.

எனவே வழக்கமான பிழைத்திருத்த கருவிகளுக்கு பதிலாக ஜிடிபி வரிசைப்படுத்தல் பிழைத்திருத்தத்திற்கான வேறுபட்ட கருவிகள் என்னிடம் உள்ளன. மேலும் "இந்த மென்பொருள் எனக்கு ஏன் வேலை செய்யவில்லை?" போன்ற சிக்கலைக் கையாள்வதற்கான எனது விருப்பமான கருவி. அழைக்கப்பட்டது ஸ்ட்ரேஸ்.

ஸ்ட்ரேஸ் என்றால் என்ன?

ஸ்ட்ரேஸ் "சிஸ்டம் கால் டிரேசிங்" க்கான கருவியாகும். இது முதலில் லினக்ஸிற்காக உருவாக்கப்பட்டது, ஆனால் அதே பிழைத்திருத்த தந்திரங்களை மற்ற கணினிகளுக்கான கருவிகள் மூலம் செய்யலாம் (DTrace அல்லது ktrace).

அடிப்படை பயன்பாடு மிகவும் எளிது. நீங்கள் எந்த கட்டளையுடனும் ஸ்ட்ரேஸை இயக்க வேண்டும், மேலும் அது அனைத்து கணினி அழைப்புகளையும் வெளியேற்றும் (முதலில் நீங்கள் அதை நீங்களே நிறுவ வேண்டும் என்றாலும் ஸ்ட்ரேஸ்):

$ 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 நிலையான நூலகம் ஒரு செயல்பாட்டு அழைப்பைக் கொண்டுள்ளது எழுது (), இது கணினி அழைப்பிற்கான அனைத்து கட்டமைப்பு-குறிப்பிட்ட குறியீடுகளையும் கொண்டுள்ளது எழுத.

ஸ்ட்ரேஸ் மூலம் மென்பொருள் வரிசைப்படுத்தல் பிழைத்திருத்தம்

சுருக்கமாக, ஒரு பயன்பாட்டிற்கும் அதன் சூழலுக்கும் (கணினி அமைப்புகள்) இடையேயான எந்தவொரு தொடர்பும் கணினி அழைப்புகள் மூலம் மேற்கொள்ளப்படுகிறது. எனவே, மென்பொருள் ஒரு கணினியில் வேலை செய்யாமல், மற்றொரு கணினியில் வேலை செய்யும் போது, ​​கணினி அழைப்பு டிரேசிங் முடிவுகளைப் பார்ப்பது நல்லது. இன்னும் குறிப்பாக, சிஸ்டம் கால் ட்ரேஸைப் பயன்படுத்தி பகுப்பாய்வு செய்யக்கூடிய பொதுவான புள்ளிகளின் பட்டியல் இங்கே:

  • கன்சோல் I/O
  • நெட்வொர்க் I/O
  • கோப்பு முறைமை அணுகல் மற்றும் கோப்பு I/O
  • ஒரு செயல்முறை நூலின் வாழ்நாளை நிர்வகித்தல்
  • குறைந்த அளவிலான நினைவக மேலாண்மை
  • குறிப்பிட்ட சாதன இயக்கிகளுக்கான அணுகல்

ஸ்ட்ரேஸை எப்போது பயன்படுத்த வேண்டும்?

கோட்பாட்டில், ஸ்ட்ரேஸ் பயனர் இடத்தில் எந்த நிரலுடனும் பயன்படுத்தப்படுகிறது, ஏனெனில் பயனர் இடத்தில் எந்த நிரலும் கணினி அழைப்புகளை செய்ய வேண்டும். இது தொகுக்கப்பட்ட, குறைந்த-நிலை நிரல்களுடன் மிகவும் திறமையாக வேலை செய்கிறது, ஆனால் இயக்க நேரம் மற்றும் மொழிபெயர்ப்பாளரின் கூடுதல் சத்தத்தை நீங்கள் குறைக்க முடிந்தால், இது பைதான் போன்ற உயர்-நிலை மொழிகளிலும் வேலை செய்கிறது.

அதன் அனைத்து சிறப்பிலும் ஸ்ட்ரேஸ் ஒரு கணினியில் நன்றாக வேலை செய்யும் மென்பொருளின் பிழைத்திருத்தத்தின் போது தன்னை வெளிப்படுத்துகிறது, ஆனால் திடீரென்று மற்றொன்றில் வேலை செய்வதை நிறுத்துகிறது, கோப்புகள், அனுமதிகள் அல்லது சில கட்டளைகளை இயக்குவதற்கான தோல்வியுற்ற முயற்சிகள் பற்றிய தெளிவற்ற செய்திகளை உருவாக்குகிறது. சான்றிதழ் சரிபார்ப்புப் பிழைகள் போன்ற உயர்மட்டச் சிக்கல்களுடன் நன்றாக இணைகிறது. பொதுவாக இதற்கு ஒரு கலவை தேவைப்படுகிறது ஸ்ட்ரேஸ், சில நேரங்களில் சுவடு மற்றும் உயர் நிலை கருவிகள் (கட்டளை வரி கருவி போன்றவை OpenSSL சான்றிதழை பிழைத்திருத்தம் செய்ய).

தனித்தனி சேவையகத்தை உதாரணமாகப் பயன்படுத்துவோம், ஆனால் சிஸ்டம் கால் டிரேசிங் என்பது மிகவும் சிக்கலான வரிசைப்படுத்தல் தளங்களில் அடிக்கடி செய்யப்படலாம். நீங்கள் சரியான கருவிகளைத் தேர்வு செய்ய வேண்டும்.

எளிய பிழைத்திருத்த உதாரணம்

நீங்கள் அற்புதமான சர்வர் அப்ளிகேஷன் foo ஐ இயக்க விரும்புகிறீர்கள் என்று வைத்துக்கொள்வோம், இதைத்தான் நீங்கள் முடிக்கிறீர்கள்:

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

நீங்கள் எழுதிய உள்ளமைவு கோப்பைக் கண்டுபிடிக்க முடியவில்லை. சில நேரங்களில் தொகுப்பு மேலாளர்கள் ஒரு பயன்பாட்டை தொகுக்கும்போது, ​​அவர்கள் எதிர்பார்க்கும் கோப்பு இருப்பிடங்களை மேலெழுதுவதால் இது நிகழ்கிறது. ஒரு விநியோகத்திற்கான நிறுவல் வழிகாட்டியைப் பின்பற்றினால், மற்றொன்றில் நீங்கள் எதிர்பார்த்த இடத்திலிருந்து முற்றிலும் வேறுபட்ட கோப்புகளைக் காணலாம். உள்ளமைவு கோப்பை எங்கு தேடுவது என்று பிழைச் செய்தி சொன்னால், சிக்கலை ஓரிரு வினாடிகளில் தீர்க்க முடியும், ஆனால் அது இல்லை. எனவே எங்கு பார்க்க வேண்டும்?

மூலக் குறியீட்டிற்கான அணுகல் உங்களிடம் இருந்தால், நீங்கள் அதைப் படித்து எல்லாவற்றையும் கண்டுபிடிக்கலாம். ஒரு நல்ல காப்புப் பிரதி திட்டம், ஆனால் விரைவான தீர்வு அல்ல. நீங்கள் ஒரு படிப்படியான பிழைத்திருத்தியை நாடலாம் ஜிடிபி நிரல் என்ன செய்கிறது என்பதைப் பார்க்கவும், ஆனால் சுற்றுச்சூழலுடன் தொடர்புகொள்வதைக் காட்ட குறிப்பாக வடிவமைக்கப்பட்ட ஒரு கருவியைப் பயன்படுத்துவது மிகவும் பயனுள்ளதாக இருக்கும்: ஸ்ட்ரேஸ்.

முடிவுக்கு ஸ்ட்ரேஸ் தேவையற்றதாக தோன்றலாம், ஆனால் நல்ல செய்தி என்னவென்றால், அதில் பெரும்பாலானவை பாதுகாப்பாக புறக்கணிக்கப்படலாம். டிரேஸ் முடிவுகளை ஒரு தனி கோப்பில் சேமிக்க -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, பாதுகாக்க, குயில் குறைந்த-நிலை நினைவகத்தைக் கண்டறிதல் மற்றும் டைனமிக் லைப்ரரிகளைக் காண்பித்தல் போன்ற விஷயங்களுக்கு.) உண்மையில், வெளியீட்டின் பிழைத்திருத்தத்தின் போது ஸ்ட்ரேஸ் கடைசியில் இருந்து படிப்பது நல்லது. கீழே ஒரு சவால் இருக்கும் எழுத, இது ஒரு பிழை செய்தியைக் காட்டுகிறது. நாங்கள் மேலே பார்த்து, முதல் தவறான கணினி அழைப்பைப் பார்க்கிறோம் - அழைப்பு openat, இது ஒரு பிழையை வீசுகிறது ENOENT (“கோப்பு அல்லது அடைவு கிடைக்கவில்லை”) திறக்க முயற்சிக்கிறது /etc/foo/config.json. இங்குதான் கட்டமைப்பு கோப்பு இருக்க வேண்டும்.

இது ஒரு உதாரணம், ஆனால் நான் பயன்படுத்தும் 90% நேரத்தை நான் கூறுவேன் ஸ்ட்ரேஸ், இதை விட கடினமான ஒன்றும் செய்ய முடியாது. ஒரு முழுமையான படிப்படியான பிழைத்திருத்த வழிகாட்டி கீழே உள்ளது:

  • ஒரு நிரலில் இருந்து சிஸ்டம்-ஒய் பிழை பற்றிய தெளிவற்ற செய்தியின் காரணமாக வருத்தமடைக
  • நிரலை மீண்டும் தொடங்கவும் ஸ்ட்ரேஸ்
  • சுவடு முடிவுகளில் பிழை செய்தியைக் கண்டறியவும்
  • தோல்வியுற்ற முதல் கணினி அழைப்பைத் தாக்கும் வரை மேலே செல்லவும்

படி 4 இல் உள்ள கணினி அழைப்பு என்ன தவறு என்பதை வெளிப்படுத்தும்.

குறிப்புகள்

மிகவும் சிக்கலான பிழைத்திருத்தத்திற்கான உதாரணத்தைக் காண்பிக்கும் முன், பயனுள்ள பயன்பாட்டிற்கான சில தந்திரங்களைக் காண்பிப்பேன் ஸ்ட்ரேஸ்:

மனிதன் உன் நண்பன்

பல *nix கணினிகளில், கர்னலுக்கான கணினி அழைப்புகளின் முழுமையான பட்டியலை இயக்குவதன் மூலம் பெறலாம் மனிதன் syscalls. போன்ற விஷயங்களைக் காண்பீர்கள் brk(2), அதாவது இயங்குவதன் மூலம் கூடுதல் தகவல்களைப் பெறலாம் மனிதன் 2 brk.

சிறிய ரேக்: மனிதன் 2 முட்கரண்டி ஷெல்லுக்கான பக்கத்தை எனக்குக் காட்டுகிறது முள் கரண்டி() в GNU libc, இது, அழைப்பதன் மூலம் செயல்படுத்தப்படுகிறது குளோன்(). சொற்பொருளை அழைக்கவும் போர்க் பயன்படுத்தி நிரலை எழுதினால் அப்படியே இருக்கும் முள் கரண்டி(), மற்றும் ட்ரேஸை இயக்கவும் - நான் எந்த அழைப்புகளையும் காணவில்லை போர்க், அவர்களுக்கு பதிலாக இருக்கும் குளோன்(). நீங்கள் மூலத்தை வெளியீட்டுடன் ஒப்பிடத் தொடங்கினால், இத்தகைய ரேக்குகள் உங்களை குழப்புகின்றன ஸ்ட்ரேஸ்.

வெளியீட்டை ஒரு கோப்பில் சேமிக்க -o ஐப் பயன்படுத்தவும்

ஸ்ட்ரேஸ் விரிவான வெளியீட்டை உருவாக்க முடியும், எனவே தனித்தனி கோப்புகளில் (மேலே உள்ள எடுத்துக்காட்டில் உள்ளதைப் போல) சுவடு முடிவுகளை சேமிப்பது பெரும்பாலும் பயனுள்ளதாக இருக்கும். நிரல் வெளியீட்டையும் வெளியீட்டையும் குழப்புவதைத் தவிர்க்கவும் இது உதவுகிறது ஸ்ட்ரேஸ் கன்சோலில்.

கூடுதல் வாதத் தரவைப் பார்க்க -s ஐப் பயன்படுத்தவும்

மேலே உள்ள எடுத்துக்காட்டு ட்ரேஸில் பிழைச் செய்தியின் இரண்டாம் பாதி காட்டப்படவில்லை என்பதை நீங்கள் கவனித்திருக்கலாம். அது ஏனெனில் ஸ்ட்ரேஸ் இயல்புநிலை சரம் வாதத்தின் முதல் 32 பைட்டுகளை மட்டுமே காட்டுகிறது. நீங்கள் மேலும் பார்க்க விரும்பினால், இதுபோன்ற ஒன்றைச் சேர்க்கவும் -s 128 அழைப்புக்கு ஸ்ட்ரேஸ்.

-y கோப்புகள், சாக்கெட்டுகள் போன்றவற்றைக் கண்காணிப்பதை எளிதாக்குகிறது.

"அனைத்தும் கோப்பு" என்பது ஒரு கோப்பு அல்லது நெட்வொர்க் அல்லது இடைசெயல் குழாய்களுக்குப் பொருந்தக்கூடிய அனைத்து I/O ஐயும் கோப்பு விளக்கங்களைப் பயன்படுத்தி நிக்ஸ் அமைப்புகள் செய்கின்றன. இது நிரலாக்கத்திற்கு வசதியானது, ஆனால் நீங்கள் பொதுவாகப் பார்க்கும்போது உண்மையில் என்ன நடக்கிறது என்பதைக் கண்காணிப்பதை கடினமாக்குகிறது படிக்க и எழுத கணினி அழைப்பு டிரேஸ் முடிவுகளில்.

ஒரு ஆபரேட்டரைச் சேர்ப்பதன் மூலம் ஒய், நீங்கள் கட்டாயப்படுத்துவீர்கள் ஸ்ட்ரேஸ் வெளியீட்டில் உள்ள ஒவ்வொரு கோப்பு விளக்கத்தையும் அது எதைச் சுட்டிக்காட்டுகிறது என்பதைக் குறிப்புடன் குறிப்பிடவும்.

-p** உடன் ஏற்கனவே இயங்கும் செயல்முறையுடன் இணைக்கவும்

கீழே உள்ள எடுத்துக்காட்டில் இருந்து நீங்கள் பார்ப்பது போல், சில நேரங்களில் நீங்கள் ஏற்கனவே இயங்கும் ஒரு நிரலைக் கண்டுபிடிக்க வேண்டும். இது செயல்முறை 1337 ஆக இயங்குகிறது என்று தெரிந்தால் (வெளியீட்டிலிருந்து சொல்லுங்கள் ps), பிறகு நீங்கள் அதை இப்படிக் கண்டறியலாம்:

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

உங்களுக்கு ரூட் உரிமைகள் தேவைப்படலாம்.

குழந்தை செயல்முறைகளை கண்காணிக்க -f ஐப் பயன்படுத்தவும்

ஸ்ட்ரேஸ் இயல்பாக, இது ஒரே ஒரு செயல்முறையை மட்டுமே கண்டறியும். இந்த செயல்முறை குழந்தை செயல்முறைகளை உருவாக்கினால், குழந்தை செயல்முறையை உருவாக்கும் கணினி அழைப்பைக் காணலாம், ஆனால் குழந்தை செயல்முறையின் கணினி அழைப்புகள் காட்டப்படாது.

குழந்தை செயல்பாட்டில் பிழை இருப்பதாக நீங்கள் நினைத்தால், அறிக்கையைப் பயன்படுத்தவும் -f, இது அதன் தடமறிதலைச் செயல்படுத்தும். இதன் குறைபாடு என்னவென்றால், வெளியீடு உங்களை மேலும் குழப்பிவிடும். எப்பொழுது ஸ்ட்ரேஸ் ஒரு செயல்முறை அல்லது ஒரு தொடரை ட்ரேஸ் செய்கிறது, இது அழைப்பு நிகழ்வுகளின் ஒற்றை ஸ்ட்ரீமைக் காட்டுகிறது. ஒரே நேரத்தில் பல செயல்முறைகளைக் கண்டறியும் போது, ​​ஒரு செய்தியின் மூலம் அழைப்பின் தொடக்கத்தை நீங்கள் காணலாம் , பின்னர் - பிற மரணதண்டனை கிளைகளுக்கான அழைப்புகளின் கொத்து, பின்னர் மட்டுமே - முதல் ஒன்றின் முடிவு <...foocall மீண்டும் தொடங்கப்பட்டது>. அல்லது ஆபரேட்டரைப் பயன்படுத்தி அனைத்து சுவடு முடிவுகளையும் வெவ்வேறு கோப்புகளாகப் பிரிக்கவும் -ff (விவரங்கள் தலைமை மீது ஸ்ட்ரேஸ்).

-e ஐப் பயன்படுத்தி தடயங்களை வடிகட்டவும்

நீங்கள் பார்க்க முடியும் என, தடயத்தின் விளைவாக சாத்தியமான அனைத்து கணினி அழைப்புகளின் உண்மையான குவியல் ஆகும். கொடி -e நீங்கள் தடயத்தை வடிகட்டலாம் (பார்க்க வழிகாட்டி மீது ஸ்ட்ரேஸ்) முக்கிய நன்மை என்னவென்றால், ஒரு முழு ட்ரேஸைச் செய்வதை விட வடிகட்டப்பட்ட ட்ரேஸை இயக்குவது வேகமானது க்ரெப்` மணிக்கு. உண்மையைச் சொல்வதானால், நான் எப்போதும் கவலைப்படுவதில்லை.

எல்லா தவறுகளும் மோசமானவை அல்ல

ஒரு எளிய மற்றும் பொதுவான உதாரணம், ஒரே நேரத்தில் பல இடங்களில் கோப்பைத் தேடும் ஒரு நிரல், இயங்கக்கூடிய கோப்பைக் கொண்ட கோப்பகத்தைத் தேடும் ஷெல் போன்றது:

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

"பிழையைப் புகாரளிப்பதற்கு முன் கடைசியாக தோல்வியடைந்த கோரிக்கை" போன்ற ஹியூரிஸ்டிக்ஸ் தொடர்புடைய பிழைகளைக் கண்டறிவதில் சிறந்தது. அது எப்படியிருந்தாலும், கடைசியில் இருந்து தொடங்குவது தர்க்கரீதியானது.

சி ப்ரோகிராமிங் டுடோரியல்கள் சிஸ்டம் கால்களைப் புரிந்துகொள்ள உதவும்.

சி லைப்ரரிகளுக்கான நிலையான அழைப்புகள் கணினி அழைப்புகள் அல்ல, ஆனால் மெல்லிய மேற்பரப்பு அடுக்கு மட்டுமே. எனவே, சியில் எப்படி, என்ன செய்ய வேண்டும் என்பதை சிறிதளவாவது புரிந்து கொண்டால், சிஸ்டம் கால் டிரேஸின் முடிவுகளைப் புரிந்துகொள்வது எளிதாக இருக்கும். எடுத்துக்காட்டாக, நெட்வொர்க் அமைப்புகளுக்கான அழைப்புகளை பிழைத்திருத்துவதில் சிக்கல் உள்ளது, அதே கிளாசிக்கைப் பாருங்கள் பிணைய நிரலாக்கத்திற்கான பீஜாவின் வழிகாட்டி.

மிகவும் சிக்கலான பிழைத்திருத்த உதாரணம்

எளிமையான பிழைத்திருத்தத்தின் உதாரணம் வேலை செய்யும் போது நான் பெரும்பாலும் சமாளிக்க வேண்டிய ஒரு உதாரணம் என்று நான் ஏற்கனவே சொன்னேன் ஸ்ட்ரேஸ். இருப்பினும், சில நேரங்களில் உண்மையான விசாரணை தேவைப்படுகிறது, எனவே மேம்பட்ட பிழைத்திருத்தத்திற்கான நிஜ வாழ்க்கை உதாரணம் இங்கே.

bcron - பணி செயலாக்க திட்டமிடல், *நிக்ஸ் டெமானின் மற்றொரு செயல்படுத்தல் கிரான். இது சர்வரில் நிறுவப்பட்டுள்ளது, ஆனால் அட்டவணையை யாராவது திருத்த முயலும்போது, ​​இதுதான் நடக்கும்:

# 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 எதைக் குறிக்கிறது என்பதைக் கண்டுபிடிப்பது எப்படி? இந்த குறிப்பிட்ட வழக்கில், நீங்கள் இயக்கலாம் ஸ்ட்ரேஸ் இயக்குனருடன் ஒய் (மேலே பார்க்கவும்) அது தானாகவே உங்களுக்குச் சொல்லும், ஆனால் இது போன்ற விஷயங்களைக் கண்டுபிடிக்க, டிரேஸ் முடிவுகளை எப்படிப் படிப்பது மற்றும் அலசுவது என்பதை அறிவது பயனுள்ளது.

கோப்பு விளக்கியின் ஆதாரம் பல கணினி அழைப்புகளில் ஒன்றாக இருக்கலாம் (இது அனைத்தும் டிஸ்கிரிப்டர் எதற்காக உள்ளது - ஒரு கன்சோல், நெட்வொர்க் சாக்கெட், கோப்பு அல்லது வேறு ஏதாவது), ஆனால் அது எப்படியிருந்தாலும், நாங்கள் தேடுகிறோம் 3 ஐத் திருப்பி அழைப்புகள் (அதாவது, டிரேசிங் முடிவுகளில் "= 3" ஐத் தேடுகிறோம்). இந்த முடிவில், அவற்றில் 2 உள்ளன: openat மிக மேல் மற்றும் சாக்கெட் மத்தியில். openat கோப்பை திறக்கிறது ஆனால் நெருக்கமான(3) பின்னர் அது மீண்டும் மூடுகிறது என்பதைக் காண்பிக்கும். (ரேக்: ஃபைல் டிஸ்கிரிப்டர்கள் திறக்கப்பட்டு மூடப்படும்போது மீண்டும் பயன்படுத்தப்படலாம்). அழைப்பு சாக்கெட் () இதற்கு முன் கடைசியாக இருப்பதால் பொருத்தமானது படி(), மற்றும் bcrontab ஒரு சாக்கெட் மூலம் ஏதாவது வேலை செய்கிறது என்று மாறிவிடும். கோப்பு விவரிப்பான் தொடர்புடையது என்பதை அடுத்த வரி காட்டுகிறது unix டொமைன் சாக்கெட் வரும் வழியில் /var/run/bcron-spool.

எனவே, தொடர்புடைய செயல்முறையை நாம் கண்டுபிடிக்க வேண்டும் யுனிக்ஸ் சாக்கெட் மறுபுறம். இந்த நோக்கத்திற்காக இரண்டு நேர்த்தியான தந்திரங்கள் உள்ளன, இவை இரண்டும் சர்வர் வரிசைப்படுத்தல்களை பிழைத்திருத்தத்திற்கு பயனுள்ளதாக இருக்கும். முதலில் பயன்படுத்துவது , 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, செயல்முறை ஐடி 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 முதலியன) இந்த செயல்முறை ஒரு குழந்தை செயல்முறைக்கு வித்திடுகிறது, இது நீங்கள் யூகித்தபடி, உண்மையான வேலையைச் செய்கிறது. நீங்கள் அவளைப் பிடிக்க வேண்டும் என்றால், அழைப்பில் சேர்க்கவும் ஸ்ட்ரேஸ் -எஃப். புதிய முடிவுகளில் உள்ள பிழைச் செய்தியை ஸ்ட்ரேஸுடன் தேடும்போது இதுதான் நமக்குக் கிடைக்கும் -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 +++

(நீங்கள் தொலைந்துவிட்டால், எனது முந்தைய இடுகையைப் படிக்க விரும்பலாம் நிக்ஸ் செயல்முறை மேலாண்மை மற்றும் ஷெல்களைப் பற்றி.) எனவே, சர்வர் 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

அங்கேதான் நாய் புதைக்கப்பட்டது! சர்வர் ஒரு பயனர் கிரானாக இயங்குகிறது, ஆனால் ரூட் மட்டுமே கோப்பகத்தில் எழுத அனுமதி உள்ளது /var/spool/cron/tmp/. எளிய கட்டளை சோவ்ன் கிரான் /var/spool/cron/tmp/ கட்டாயப்படுத்துவார்கள் bcron சரியாக வேலை. (அது பிரச்சனை இல்லை என்றால், அடுத்த சந்தேகத்திற்குரியது SELinux அல்லது AppArmor போன்ற கர்னல் பாதுகாப்பு தொகுதி ஆகும், எனவே நான் கர்னல் செய்தி பதிவை சரிபார்க்கிறேன் dmesg.)

மொத்தம்

சிஸ்டம் கால் ட்ரேஸ்கள் ஒரு தொடக்கநிலையாளருக்கு அதிகமாக இருக்கலாம், ஆனால் அவை பொதுவான வரிசைப்படுத்தல் சிக்கல்களின் முழு வகுப்பையும் பிழைத்திருத்துவதற்கான விரைவான வழியாகும் என்று நான் நம்புகிறேன். பல செயல்முறைகளை பிழைத்திருத்த முயற்சிப்பதை கற்பனை செய்து பாருங்கள் bcronஒரு படிப்படியான பிழைத்திருத்தியைப் பயன்படுத்துதல்.

சிஸ்டம் கால் செயினுடன் பின்னோக்கி முடிவுகளைப் பாகுபடுத்துவதற்கு திறமை தேவை, ஆனால் நான் சொன்னது போல், எப்போதும், பயன்படுத்தி ஸ்ட்ரேஸ், நான் சுவடு முடிவைப் பெறுகிறேன் மற்றும் முடிவில் இருந்து தொடங்கும் பிழைகளைத் தேடுகிறேன். எப்படியும், ஸ்ட்ரேஸ் பிழைத்திருத்தத்தில் நிறைய நேரத்தைச் சேமிக்க உதவுகிறது. உங்களுக்கும் பயனுள்ளதாக இருக்கும் என்று நம்புகிறேன்.

ஆதாரம்: www.habr.com

கருத்தைச் சேர்