స్ట్రేస్‌తో డీబగ్గింగ్ సాఫ్ట్‌వేర్ విస్తరణ

స్ట్రేస్‌తో డీబగ్గింగ్ సాఫ్ట్‌వేర్ విస్తరణ

నా రోజు ఉద్యోగం ఎక్కువగా సాఫ్ట్‌వేర్ విస్తరణ, అంటే నేను ఇలాంటి ప్రశ్నలకు సమాధానం ఇవ్వడానికి చాలా సమయాన్ని వెచ్చిస్తాను:

  • ఈ సాఫ్ట్‌వేర్ డెవలపర్ కోసం పని చేస్తుంది, కానీ నా కోసం కాదు. ఎందుకు?
  • నిన్న ఈ సాఫ్ట్‌వేర్ నా కోసం పనిచేసింది, కానీ నేడు అది పని చేయలేదు. ఎందుకు?

ఇది సాధారణ సాఫ్ట్‌వేర్ డీబగ్గింగ్ నుండి కొద్దిగా భిన్నంగా ఉండే ఒక రకమైన డీబగ్గింగ్. రెగ్యులర్ డీబగ్గింగ్ అనేది కోడ్ యొక్క లాజిక్ గురించి, కానీ డిప్లాయ్‌మెంట్ డీబగ్గింగ్ అనేది కోడ్ మరియు పర్యావరణం మధ్య పరస్పర చర్య. సమస్యకు మూలం తార్కిక లోపం అయినప్పటికీ, ప్రతిదీ ఒక యంత్రంలో పని చేస్తుంది మరియు మరొకదానిపై పనిచేయదు అంటే సమస్య ఏదో వాతావరణంలో ఉందని అర్థం.

కాబట్టి సాధారణ డీబగ్గింగ్ సాధనాలకు బదులుగా gdb డీబగ్గింగ్ డిప్లాయ్‌మెంట్ కోసం నా దగ్గర వేరే సెట్ టూల్స్ ఉన్నాయి. మరియు "ఈ సాఫ్ట్‌వేర్ నా కోసం ఎందుకు పని చేయదు?" వంటి సమస్యతో వ్యవహరించడానికి నాకు ఇష్టమైన సాధనం. అని పిలిచారు పట్టీ.

స్ట్రేస్ అంటే ఏమిటి?

పట్టీ "సిస్టమ్ కాల్ ట్రేసింగ్" కోసం ఒక సాధనం. ఇది మొదట Linux కోసం సృష్టించబడింది, అయితే అదే డీబగ్గింగ్ ట్రిక్‌లను ఇతర సిస్టమ్‌ల కోసం సాధనాలతో చేయవచ్చు (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

మీరు వ్రాసిన కాన్ఫిగరేషన్ ఫైల్‌ని అది కనుగొనలేకపోయింది. కొన్నిసార్లు ప్యాకేజీ నిర్వాహకులు అప్లికేషన్‌ను కంపైల్ చేసినప్పుడు, వారు ఆశించిన ఫైల్ స్థానాలను భర్తీ చేస్తారు కాబట్టి ఇది జరుగుతుంది. మరియు మీరు ఒక డిస్ట్రిబ్యూషన్ కోసం ఇన్‌స్టాలేషన్ గైడ్‌ను అనుసరిస్తే, మరొకదానిలో మీరు ఊహించిన దానికంటే పూర్తిగా భిన్నమైన ఫైల్‌లను మీరు కనుగొంటారు. కాన్ఫిగరేషన్ ఫైల్ కోసం ఎక్కడ వెతకాలో ఎర్రర్ మెసేజ్ చెబితే సమస్య కొన్ని సెకన్లలో పరిష్కరించబడుతుంది, కానీ అది జరగదు. కాబట్టి ఎక్కడ చూడాలి?

మీకు సోర్స్ కోడ్‌కు యాక్సెస్ ఉంటే, మీరు దాన్ని చదివి ప్రతిదీ తెలుసుకోవచ్చు. మంచి బ్యాకప్ ప్లాన్, కానీ వేగవంతమైన పరిష్కారం కాదు. మీరు వంటి దశల వారీ డీబగ్గర్‌ని ఆశ్రయించవచ్చు 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, రక్షించండి, పిట్ట తక్కువ-స్థాయి మెమరీని గుర్తించడం మరియు డైనమిక్ లైబ్రరీలను ప్రదర్శించడం వంటి వాటి కోసం.) వాస్తవానికి, అవుట్‌పుట్‌ను డీబగ్ చేసే సమయంలో పట్టీ చివరి నుండి చదవడం మంచిది. క్రింద ఒక సవాలు ఉంటుంది వ్రాయడానికి, ఇది దోష సందేశాన్ని ప్రదర్శిస్తుంది. మేము పైన చూస్తున్నాము మరియు మొదటి తప్పు సిస్టమ్ కాల్‌ని చూస్తాము - కాల్ ఓపెన్, ఇది లోపాన్ని విసురుతుంది ENOENT (“ఫైల్ లేదా డైరెక్టరీ కనుగొనబడలేదు”) తెరవడానికి ప్రయత్నిస్తున్నారు /etc/foo/config.json. ఇక్కడే కాన్ఫిగరేషన్ ఫైల్ ఉండాలి.

ఇది ఒక ఉదాహరణ మాత్రమే, కానీ నేను ఉపయోగించే 90% సమయం చెబుతాను పట్టీ, ఇంతకంటే కష్టంగా ఏమీ లేదు. దిగువన పూర్తి దశల వారీ డీబగ్గింగ్ గైడ్ ఉంది:

  • ప్రోగ్రామ్ నుండి సిస్టమ్-y లోపం గురించి అస్పష్టమైన సందేశం కారణంగా కలత చెందండి
  • దీనితో ప్రోగ్రామ్‌ను పునఃప్రారంభించండి పట్టీ
  • ట్రేస్ ఫలితాలలో దోష సందేశాన్ని కనుగొనండి
  • మీరు మొదటి విఫలమైన సిస్టమ్ కాల్‌ని కొట్టే వరకు పైకి వెళ్లండి

స్టెప్ 4లోని సిస్టమ్ కాల్ ఏమి తప్పు జరిగిందో బహిర్గతం చేసే అవకాశం ఉంది.

సూచనలు

మరింత సంక్లిష్టమైన డీబగ్గింగ్ యొక్క ఉదాహరణను మీకు చూపే ముందు, సమర్థవంతమైన ఉపయోగం కోసం నేను మీకు కొన్ని ఉపాయాలను చూపుతాను పట్టీ:

మనిషి మీ స్నేహితుడు

అనేక *nix సిస్టమ్స్‌లో, కెర్నల్‌కు సిస్టమ్ కాల్‌ల పూర్తి జాబితాను రన్ చేయడం ద్వారా పొందవచ్చు మనిషి syscalls. వంటి వాటిని మీరు చూస్తారు brk(2), అంటే రన్ చేయడం ద్వారా మరింత సమాచారం పొందవచ్చు మనిషి 2 brk.

చిన్న రేక్: మనిషి 2 ఫోర్క్ షెల్ కోసం పేజీని నాకు చూపుతుంది ఫోర్క్ () в GNU libc, ఇది, కాల్ చేయడం ద్వారా అమలు చేయబడుతుంది క్లోన్(). కాల్ సెమాంటిక్స్ ఫోర్క్ మీరు ఉపయోగించి ప్రోగ్రామ్ వ్రాస్తే అలాగే ఉంటుంది ఫోర్క్ (), మరియు ట్రేస్‌ని అమలు చేయండి - నాకు కాల్‌లు ఏవీ కనుగొనబడలేదు ఫోర్క్, వాటికి బదులుగా ఉంటుంది క్లోన్(). మీరు మూలాన్ని అవుట్‌పుట్‌తో పోల్చడం ప్రారంభించినట్లయితే ఇటువంటి రేక్‌లు మిమ్మల్ని గందరగోళానికి గురిచేస్తాయి పట్టీ.

అవుట్‌పుట్‌ను ఫైల్‌లో సేవ్ చేయడానికి -o ఉపయోగించండి

పట్టీ విస్తృతమైన అవుట్‌పుట్‌ను ఉత్పత్తి చేయగలదు, కాబట్టి ట్రేస్ ఫలితాలను ప్రత్యేక ఫైల్‌లలో నిల్వ చేయడం తరచుగా ఉపయోగపడుతుంది (పై ఉదాహరణలో వలె). ఇది అవుట్‌పుట్‌తో ప్రోగ్రామ్ అవుట్‌పుట్ గందరగోళాన్ని నివారించడానికి కూడా సహాయపడుతుంది పట్టీ కన్సోల్‌లో.

మరింత ఆర్గ్యుమెంట్ డేటాను వీక్షించడానికి -s ఉపయోగించండి

ఎగువ ఉదాహరణ ట్రేస్‌లో దోష సందేశం యొక్క రెండవ సగం చూపబడలేదని మీరు గమనించి ఉండవచ్చు. ఇది ఎందుకంటే పట్టీ డిఫాల్ట్ స్ట్రింగ్ ఆర్గ్యుమెంట్ యొక్క మొదటి 32 బైట్‌లను మాత్రమే చూపుతుంది. మీరు మరిన్ని చూడాలనుకుంటే, ఇలాంటివి జోడించండి -s 128 కాల్ కు పట్టీ.

-y ఫైల్‌లు, సాకెట్లు మొదలైనవాటిని ట్రాక్ చేయడాన్ని సులభతరం చేస్తుంది.

"అన్నీ ఫైల్" అంటే *nix సిస్టమ్‌లు ఫైల్ డిస్క్రిప్టర్‌లను ఉపయోగించి అన్ని I/Oలను చేస్తాయి, అది ఫైల్ లేదా నెట్‌వర్క్ లేదా ఇంటర్‌ప్రాసెస్ పైపులకు వర్తిస్తుంది. ఇది ప్రోగ్రామింగ్‌కు అనుకూలమైనది, కానీ మీరు సాధారణంగా చూసినప్పుడు నిజంగా ఏమి జరుగుతుందో ట్రాక్ చేయడం కష్టతరం చేస్తుంది చదవండి и వ్రాయడానికి సిస్టమ్ కాల్ ట్రేస్ ఫలితాలలో.

ఆపరేటర్‌ని జోడించడం ద్వారా అవును, మీరు బలవంతం చేస్తారు పట్టీ అవుట్‌పుట్‌లోని ప్రతి ఫైల్ డిస్క్రిప్టర్‌ను అది సూచించే గమనికతో ఉల్లేఖించండి.

-p**తో ఇప్పటికే నడుస్తున్న ప్రాసెస్‌కి అటాచ్ చేయండి

దిగువ ఉదాహరణ నుండి మీరు చూసినట్లుగా, కొన్నిసార్లు మీరు ఇప్పటికే అమలులో ఉన్న ప్రోగ్రామ్‌ను కనుగొనవలసి ఉంటుంది. అది ప్రాసెస్ 1337గా నడుస్తుందని తెలిస్తే (అవుట్‌పుట్ నుండి చెప్పండి ps), అప్పుడు మీరు దీన్ని ఇలా ట్రేస్ చేయవచ్చు:

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

మీకు రూట్ హక్కులు అవసరం కావచ్చు.

పిల్లల ప్రక్రియలను పర్యవేక్షించడానికి -f ఉపయోగించండి

పట్టీ డిఫాల్ట్‌గా, ఇది ఒక ప్రక్రియను మాత్రమే ట్రేస్ చేస్తుంది. ఈ ప్రక్రియ చైల్డ్ ప్రాసెస్‌లను స్పాన్ చేస్తే, చైల్డ్ ప్రాసెస్‌ను స్పాన్ చేయడానికి సిస్టమ్ కాల్ చూడవచ్చు, కానీ చైల్డ్ ప్రాసెస్ సిస్టమ్ కాల్‌లు ప్రదర్శించబడవు.

చైల్డ్ ప్రాసెస్‌లో లోపం ఉందని మీరు అనుకుంటే, స్టేట్‌మెంట్‌ను ఉపయోగించండి -f, ఇది దాని ట్రేసింగ్‌ను ఎనేబుల్ చేస్తుంది. దీని ప్రతికూలత ఏమిటంటే, అవుట్‌పుట్ మిమ్మల్ని మరింత గందరగోళానికి గురి చేస్తుంది. ఎప్పుడు పట్టీ ఒక ప్రక్రియ లేదా ఒక థ్రెడ్‌ను ట్రేస్ చేస్తుంది, ఇది కాల్ ఈవెంట్‌ల యొక్క ఒకే స్ట్రీమ్‌ను చూపుతుంది. ఇది ఒకేసారి బహుళ ప్రాసెస్‌లను గుర్తించినప్పుడు, సందేశం ద్వారా అంతరాయం ఏర్పడిన కాల్ ప్రారంభాన్ని మీరు చూడవచ్చు , అప్పుడు - ఇతర అమలు శాఖల కోసం కాల్‌ల సమూహం, మరియు అప్పుడు మాత్రమే - మొదటిది ముగింపు <...foocall పునఃప్రారంభించబడింది>. లేదా ఆపరేటర్‌ని ఉపయోగించి అన్ని ట్రేస్ ఫలితాలను వేర్వేరు ఫైల్‌లుగా విభజించండి -ff (లో వివరాలు నాయకత్వం పై పట్టీ).

-e ఉపయోగించి ట్రేస్‌లను ఫిల్టర్ చేయండి

మీరు చూడగలిగినట్లుగా, ట్రేస్ యొక్క ఫలితం సాధ్యమయ్యే అన్ని సిస్టమ్ కాల్స్ యొక్క నిజమైన పైల్. జెండా -e మీరు ట్రేస్‌ను ఫిల్టర్ చేయవచ్చు (చూడండి గైడ్ పై పట్టీ) ప్రధాన ప్రయోజనం ఏమిటంటే, పూర్తి ట్రేస్ చేయడం కంటే ఫిల్టర్ చేసిన ట్రేస్‌ను అమలు చేయడం వేగంగా ఉంటుంది grep`వద్ద. నిజం చెప్పాలంటే, నేను దాదాపు ఎల్లప్పుడూ పట్టించుకోను.

అన్ని తప్పులు చెడ్డవి కావు

ఎక్జిక్యూటబుల్ ఫైల్‌ని కలిగి ఉన్న డైరెక్టరీ కోసం వెతుకుతున్న షెల్ వంటి అనేక ప్రదేశాలలో ఒకేసారి ఫైల్ కోసం వెతుకుతున్న ప్రోగ్రామ్ ఒక సాధారణ మరియు సాధారణ ఉదాహరణ:

$ 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 లో ఎలా మరియు ఏమి చేయాలో కనీసం కొంచెం అర్థం చేసుకుంటే, సిస్టమ్ కాల్ ట్రేస్ ఫలితాలను అర్థం చేసుకోవడం మీకు సులభం అవుతుంది. ఉదాహరణకు, నెట్‌వర్క్ సిస్టమ్‌లకు కాల్‌లను డీబగ్ చేయడంలో మీకు సమస్య ఉంది, అదే క్లాసిక్‌ని చూడండి నెట్‌వర్క్ ప్రోగ్రామింగ్‌కు బీజాస్ గైడ్.

మరింత క్లిష్టమైన డీబగ్గింగ్ ఉదాహరణ

సాధారణ డీబగ్గింగ్ యొక్క ఉదాహరణ నేను పని చేస్తున్నప్పుడు ఎక్కువగా ఎదుర్కోవాల్సిన ఉదాహరణ అని నేను ఇప్పటికే చెప్పాను పట్టీ. అయితే, కొన్నిసార్లు నిజమైన పరిశోధన అవసరమవుతుంది, కాబట్టి ఇక్కడ మరింత అధునాతన డీబగ్గింగ్ యొక్క నిజ జీవిత ఉదాహరణ ఉంది.

bcron - టాస్క్ ప్రాసెసింగ్ షెడ్యూలర్, *nix డెమోన్ యొక్క మరొక అమలు క్రాన్. ఇది సర్వర్‌లో ఇన్‌స్టాల్ చేయబడింది, కానీ ఎవరైనా షెడ్యూల్‌ను సవరించడానికి ప్రయత్నించినప్పుడు, ఇది జరుగుతుంది:

# 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 ఉన్నాయి: ఓపెన్ చాలా ఎగువన మరియు సాకెట్ మధ్యలో. ఓపెన్ ఫైల్‌ను తెరుస్తుంది కానీ దగ్గరి(3) అది మళ్లీ మూసివేయబడిందని చూపుతుంది. (రేక్: ఫైల్ డిస్క్రిప్టర్‌లు తెరిచినప్పుడు మరియు మూసివేయబడినప్పుడు వాటిని తిరిగి ఉపయోగించుకోవచ్చు). కాల్ చేయండి సాకెట్ () ఇది ముందు చివరిది కనుక తగినది చదవండి(), మరియు 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. కొత్త ఫలితంలో స్ట్రేస్‌తో ఎర్రర్ మెసేజ్‌ని సెర్చ్ చేసినప్పుడు ఇది మనకు కనిపిస్తుంది -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 +++

(మీరు పోగొట్టుకున్నట్లయితే, మీరు నా మునుపటి పోస్ట్‌ను చదవాలనుకోవచ్చు about *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

కుక్కను అక్కడే పాతిపెట్టారు! సర్వర్ వినియోగదారు క్రాన్‌గా నడుస్తుంది, అయితే డైరెక్టరీకి వ్రాయడానికి రూట్‌కు మాత్రమే అనుమతి ఉంది /var/spool/cron/tmp/. సాధారణ ఆదేశం చౌన్ క్రాన్ /var/spool/cron/tmp/ బలవంతం చేస్తుంది bcron సరిగ్గా పని చేయండి. (అది సమస్య కాకపోతే, తర్వాత అనుమానితుడు SELinux లేదా AppArmor వంటి కెర్నల్ సెక్యూరిటీ మాడ్యూల్, కాబట్టి నేను కెర్నల్ సందేశ లాగ్‌ని తనిఖీ చేస్తాను dmesg.)

మొత్తం

సిస్టమ్ కాల్ ట్రేస్‌లు ఒక అనుభవశూన్యుడు కోసం అధికంగా ఉండవచ్చు, కానీ అవి మొత్తం తరగతి సాధారణ విస్తరణ సమస్యలను డీబగ్ చేయడానికి శీఘ్ర మార్గం అని నేను చూపించానని ఆశిస్తున్నాను. మల్టీప్రాసెస్‌ను డీబగ్ చేయడానికి ప్రయత్నిస్తున్నట్లు ఊహించుకోండి bcronదశల వారీ డీబగ్గర్‌ని ఉపయోగించడం.

సిస్టమ్ కాల్ చైన్‌తో పాటు ట్రేస్ ఫలితాలను వెనుకకు అన్వయించడంలో నైపుణ్యం అవసరం, కానీ నేను చెప్పినట్లుగా, దాదాపు ఎల్లప్పుడూ ఉపయోగించడం పట్టీ, నేను ట్రేస్ ఫలితాన్ని పొందాను మరియు చివరి నుండి ప్రారంభమయ్యే లోపాల కోసం చూస్తున్నాను. ఏమైనా, పట్టీ డీబగ్గింగ్‌లో చాలా సమయాన్ని ఆదా చేయడంలో నాకు సహాయపడుతుంది. ఇది మీకు కూడా ఉపయోగపడుతుందని ఆశిస్తున్నాను.

మూలం: www.habr.com

ఒక వ్యాఖ్యను జోడించండి