كيف قام إيفان بترجمة الخطأ في الخلفية

في التعليقات على إحدى مقالاتي حول أوامر Linux shell الأساسية للمختبرين ، لوحظ بحق أنه لم يحدد استخدام الأوامر أثناء الاختبار. اعتقدت أن التأخير أفضل من عدمه ، لذلك قررت أن أحكي قصة مهندسة ضمان الجودة في Backend Vanya ، التي واجهت سلوك خدمة غير متوقع وحاولت معرفة مكان حدوث الخطأ بالضبط.







ما اختبرته فانيا



كان فانيا يعلم أنه سيختبر حزمة "nginx + service".

سأدلي هنا على الفور بملاحظة: تم اختيار هذه الحزمة لهذه المقالة لمجرد أنها يمكن أن توضح بوضوح استخدام الأدوات المساعدة المختلفة عند تصحيح مشكلة ولأن تكوينها ورفعها أمر بسيط للغاية. بالقيمة الحقيقية ، يمكن أن تكون إما مجرد خدمة أو سلسلة من الخدمات التي تقدم الطلبات لبعضها البعض.


يعمل خادم HTTP الافتراضي Python SimpleHTTPServer كخدمة ، والتي ، استجابة لطلب بدون معلمات ، تعرض محتويات الدليل الحالي:



[root@ivan test_dir_srv]# ls -l
total 0
-rw-r--r-- 1 root root 0 Aug 25 11:23 test_file
[root@ivan test_dir_srv]# python3 -m http.server --bind 127.0.0.1 8000
Serving HTTP on 127.0.0.1 port 8000 (http://127.0.0.1:8000/) ...


تم تكوين Nginx على النحو التالي:



upstream test {
    server 127.0.0.1:8000;
}

server {
    listen       80;

    location / {
        proxy_pass http://test;
    }
}


احتاجت فانيا إلى اختبار حالة اختبار واحدة: للتحقق من أن الطلب / يعمل. قام بفحص وعمل كل شيء:



MacBook-Pro-Ivan:~ ivantester$ curl http://12.34.56.78
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href="test_file">test_file</a></li>
</ul>
<hr>
</body>
</html>


ولكن بعد ذلك في مرحلة ما على منصة الاختبار ، قام المطورون بتحديث شيء ما ، وتلقى Vanya خطأ:



MacBook-Pro-Ivan:~ ivantester$ curl http://12.34.56.78
<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.14.2</center>
</body>
</html>


قرر عدم إلقاء هذا الخطأ غير المفهوم على المطورين ، ولكن للحصول على وصول ssh إلى الخادم ومعرفة ما يجري هناك. كان لديه القليل من المعرفة في مجال هذا النوع من تصحيح الأخطاء ، لكنه أراد حقًا التعلم ، لذلك تسلح بمحركات البحث والمنطق وذهب لتحديد موقع الخطأ.



فكر فانيا الأول: السجلات



في الواقع ، إذا حدث خطأ ، فأنت تحتاج فقط إلى العثور عليه في ملف السجل. لكن عليك أولاً العثور على ملف السجل نفسه. ذهبت Vanya إلى Google واكتشفت أن السجلات غالبًا ما تكون في دليل / var / log . في الواقع ، تم العثور على دليل nginx هناك:



[root@ivan ~]# ls /var/log/nginx/
access.log  access.log-20200831  error.log  error.log-20200831


نظر إيفان في السطور الأخيرة من سجل الأخطاء وأدرك الخطأ: ارتكب المطورون خطأ في تكوين nginx ، تسلل خطأ مطبعي إلى منفذ المنبع.



[root@ivan ~]# tail /var/log/nginx/error.log
2020/08/31 04:36:21 [error] 15050#15050: *90452 connect() failed (111: Connection refused) while connecting to upstream, client: 31.170.95.221, server: , request: "GET / HTTP/1.0", upstream: "http://127.0.0.1:8009/", host: "12.34.56.78"


? — . - , , . nginx , , , ?


في تلك اللحظة ، فكر فانيا: "ماذا لو كانت سجلات nginx في دليل مختلف؟ كيف أجدهم؟ " في غضون عامين ، سيكون لدى Vanya خبرة أكبر في الخدمات في Linux ، وسيعرف أن المسار إلى ملف السجل غالبًا ما يتم تمريره إلى الخدمة كوسيطة سطر أوامر ، أو يتم تضمينه في ملف التكوين ، وهو المسار الذي يتم تمريره غالبًا أيضًا إلى الخدمة كوسيطة سطر أوامر. حسنًا ، من الناحية المثالية ، يجب كتابة المسار إلى ملف السجل في وثائق الخدمة.



بالمناسبة ، من خلال ملف التكوين ، يمكنك العثور على المسار إلى ملف السجل في nginx:



[root@ivan ~]# ps ax | grep nginx | grep master
root     19899  0.0  0.0  57392  2872 ?        Ss    2019   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
[root@ivan ~]# grep "log" /etc/nginx/nginx.conf
error_log  /var/log/nginx/error.log warn;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    access_log  /var/log/nginx/access.log  main;


ماذا لو لم يكن هناك شيء في السجلات؟



في أوقات فراغه ، قرر فانيا التفكير في كيفية تعامله مع المهمة إذا لم يكتب nginx أي شيء في السجل. علم فانيا أن الخدمة كانت تستمع على المنفذ 8000 ، لذلك قرر أن ينظر إلى حركة المرور على هذا المنفذ على الخادم. ساعدته الأداة المساعدة tcpdump في ذلك . مع التكوين الصحيح ، رأى طلبًا واستجابة:



تفريغ حركة المرور على المنفذ 8000
[root@ivan ~]# tcpdump -nn -i lo -A port 8000
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
09:10:42.114284 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [S], seq 3390176024, win 43690, options [mss 65495,sackOK,TS val 830366494 ecr 0,nop,wscale 8], length 0
E..<..@.@..............@.............0.........
1~c.........
09:10:42.114293 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [S.], seq 4147196208, ack 3390176025, win 43690, options [mss 65495,sackOK,TS val 830366494 ecr 830366494,nop,wscale 8], length 0
E..<..@.@.<..........@...110.........0.........
1~c.1~c.....
09:10:42.114302 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [.], ack 1, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 0
E..4..@.@..............@.....111.....(.....
1~c.1~c.
09:10:42.114329 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [P.], seq 1:88, ack 1, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 87
E.....@.@..b...........@.....111...........
1~c.1~c.GET / HTTP/1.0
Host: test
Connection: close
User-Agent: curl/7.64.1
Accept: */*

09:10:42.114333 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [.], ack 88, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 0
E..4R/@.@............@...111...p.....(.....
1~c.1~c.
09:10:42.115062 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [P.], seq 1:155, ack 88, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 154
E...R0@.@............@...111...p...........
1~c.1~c.HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.7.2
Date: Mon, 07 Sep 2020 13:10:42 GMT
Content-type: text/html; charset=utf-8
Content-Length: 340

09:10:42.115072 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [.], ack 155, win 175, options [nop,nop,TS val 830366494 ecr 830366494], length 0
E..4.@.@..............@...p.11......(.....
1~c.1~c.
09:10:42.115094 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [P.], seq 155:495, ack 88, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 340
E...R1@.@..<.........@...11....p.....|.....
1~c.1~c.<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href="test_file">test_file</a></li>
</ul>
<hr>
</body>
</html>

09:10:42.115098 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [.], ack 495, win 180, options [nop,nop,TS val 830366494 ecr 830366494], length 0
E..4.
@.@..............@...p.13......(.....
1~c.1~c.
09:10:42.115128 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [F.], seq 495, ack 88, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 0
E..4R2@.@............@...13....p.....(.....
1~c.1~c.
09:10:42.115264 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [F.], seq 88, ack 496, win 180, options [nop,nop,TS val 830366495 ecr 830366494], length 0
E..4..@.@..............@...p.13 .....(.....
1~c.1~c.
09:10:42.115271 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [.], ack 89, win 171, options [nop,nop,TS val 830366495 ecr 830366495], length 0
E..4R3@.@............@...13 ...q.....(.....
1~c.1~c.
^C
12 packets captured
24 packets received by filter
0 packets dropped by kernel




بتكوين غير صحيح (مع المنفذ 8009 في nginx upstream) ، لم تكن هناك حركة مرور على المنفذ 8000. كان فانيا سعيدًا: الآن حتى إذا نسي المطورون الكتابة إلى السجل في حالة حدوث أخطاء في الشبكة ، فلا يزال بإمكانك على الأقل معرفة ما إذا كانت حركة المرور تذهب إلى المضيف أو المنفذ المطلوب.



ما النتيجة التي يمكن استخلاصها من هذه القصة؟ حتى في حالة عدم وجود سجلات ، فإن Linux لديه أدوات مساعدة يمكنها المساعدة في تحديد مشاكل الترجمة.


وإذا لم يكن شبكة؟



كل شيء سار بشكل جيد ، ولكن ذات يوم تلقت فانيا خطأ مرة أخرى ، ولكن هذه المرة مختلفة:



MacBook-Pro-Ivan:~ ivantester$ curl http://12.34.56.78
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
        <title>Error response</title>
    </head>
    <body>
        <h1>Error response</h1>
        <p>Error code: 404</p>
        <p>Message: File not found.</p>
        <p>Error code explanation: HTTPStatus.NOT_FOUND - Nothing matches the given URI.</p>
    </body>
</html>


ذهبت فانيا إلى الخادم مرة أخرى ، لكن هذه المرة لم تكن المشكلة متعلقة بالشبكة. قال سجل الخدمة أيضًا إن الملف غير موجود ، وقررت فانيا معرفة سبب ظهور مثل هذا الخطأ فجأة. إنه يعلم أن هناك عملية python3 -m http.server ، لكنه لا يعرف محتويات الدليل الذي تعرضه هذه الخدمة (أو ، بعبارة أخرى ، دليل العمل الحالي لهذه العملية). يكتشف بأمر lsof :



[root@ivan ~]# ps aux | grep python | grep "http.server"
root     20638  0.0  0.3 270144 13552 pts/2    S+   08:29   0:00 python3 -m http.server
[root@ivan ~]# lsof -p 20638 | grep cwd
python3 20638 root  cwd    DIR     253,1      4096 1843551 /root/test_dir_srv2


يمكن القيام بذلك أيضًا باستخدام الأمر pwdx أو باستخدام دليل proc :



[root@ivan ~]# pwdx 20638
20638: /root/test_dir_srv2
[root@ivan ~]# ls -l /proc/20638/cwd
lrwxrwxrwx 1 root root 0 Aug 31 08:37 /proc/20638/cwd -> /root/test_dir_srv2


مثل هذا الدليل موجود بالفعل على الخادم ، ويحتوي على ملف باسم test_file . ما هو الأمر؟ بحث إيفان في جوجل ووجد أداة الدعامة ، التي يمكنك من خلالها معرفة النظام الذي يسميه أداء العملية ( بالمناسبة ، هناك مقال جيد عن حبري حول الاستقامة ، ولا حتى مقال واحد ). يمكنك إما بدء عملية جديدة من خلال strace ، أو الاتصال بهذه الأداة المساعدة لعملية قيد التشغيل بالفعل. الخيار الثاني مناسب لفانيا:



إخراج دعامة
[root@ivan ~]# strace -ff -p 20638
strace: Process 20638 attached
restart_syscall(<... resuming interrupted poll ...>) = 0
poll([{fd=4, events=POLLIN}], 1, 500)   = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500)   = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500)   = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500)   = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500)   = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500)   = 1 ([{fd=4, revents=POLLIN}])
accept4(4, {sa_family=AF_INET, sin_port=htons(57530), sin_addr=inet_addr("127.0.0.1")}, [16], SOCK_CLOEXEC) = 5
clone(child_stack=0x7f2beeb28fb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f2beeb299d0, tls=0x7f2beeb29700, child_tidptr=0x7f2beeb299d0) = 21062
futex(0x11204d0, FUTEX_WAIT_PRIVATE, 0, NULLstrace: Process 21062 attached
 <unfinished ...>
[pid 21062] set_robust_list(0x7f2beeb299e0, 24) = 0
[pid 21062] futex(0x11204d0, FUTEX_WAKE_PRIVATE, 1) = 1
[pid 20638] <... futex resumed> )       = 0
[pid 20638] futex(0x921c9c, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 27, {1598879772, 978949000}, ffffffff <unfinished ...>
[pid 21062] futex(0x921c9c, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x921c98, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
[pid 20638] <... futex resumed> )       = 0
[pid 20638] futex(0x921cc8, FUTEX_WAIT_PRIVATE, 2, NULL <unfinished ...>
[pid 21062] futex(0x921cc8, FUTEX_WAKE_PRIVATE, 1) = 1
[pid 20638] <... futex resumed> )       = 0
[pid 20638] futex(0x921cc8, FUTEX_WAKE_PRIVATE, 1) = 0
[pid 20638] poll([{fd=4, events=POLLIN}], 1, 500 <unfinished ...>
[pid 21062] recvfrom(5, "GET / HTTP/1.1\r\nConnection: upgr"..., 8192, 0, NULL, NULL) = 153
[pid 21062] stat("/root/test_dir_srv/", 0x7f2beeb27350) = -1 ENOENT (No such file or directory)
[pid 21062] open("/root/test_dir_srv/", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 21062] write(2, "127.0.0.1 - - [31/Aug/2020 09:16"..., 70) = 70
[pid 21062] write(2, "127.0.0.1 - - [31/Aug/2020 09:16"..., 60) = 60
[pid 21062] sendto(5, "HTTP/1.0 404 File not found\r\nSer"..., 184, 0, NULL, 0) = 184
[pid 21062] sendto(5, "<!DOCTYPE HTML PUBLIC \"-//W3C//D"..., 469, 0, NULL, 0) = 469
[pid 21062] shutdown(5, SHUT_WR)        = 0
[pid 21062] close(5)                    = 0
[pid 21062] madvise(0x7f2bee329000, 8368128, MADV_DONTNEED) = 0
[pid 21062] exit(0)                     = ?
[pid 21062] +++ exited with 0 +++
<... poll resumed> )                    = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500)   = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500)   = 0 (Timeout)
poll([{fd=4, events=POLLIN}], 1, 500^Cstrace: Process 20638 detached
 <detached ...>




عادةً ما يكون إخراج strace ضخمًا جدًا (وربما كبير جدًا) ، لذلك من الملائم إعادة توجيهه على الفور إلى ملف ثم البحث عن استدعاءات النظام الضرورية فيه. في هذه الحالة ، يمكنك أن تجد على الفور أن الخدمة تحاول فتح الدليل / root / test_dir_srv / - قام شخص ما بإعادة تسميتها ولم يقم بإعادة تشغيل الخدمة بعد ذلك ، لذا فإنها تُرجع 404.



إذا فهمت على الفور مكالمات النظام التي تحتاج إلى النظر فيها ، يمكنك استخدام الخيار :



[root@ivan ~]# strace -ff -e trace=open,stat -p 20638
strace: Process 20638 attached
strace: Process 21396 attached
[pid 21396] stat("/root/test_dir_srv/", 0x7f2beeb27350) = -1 ENOENT (No such file or directory)
[pid 21396] open("/root/test_dir_srv/", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 21396] +++ exited with 0 +++
^Cstrace: Process 20638 detached


: « » , strace. , , (, / ), . ltrace.


- ?



لم تتوقف فانيا عند هذا الحد ووجدت أن هناك مصحح أخطاء مشروع جنو - GDB . بمساعدتها ، يمكنك " الدخول" في العملية وحتى تعديلها قليلاً. وقررت فانيا محاولة العثور على الخطأ الأخير باستخدام GDB . اقترح أنه نظرًا لأن الخدمة تعرض محتويات الدليل ، فيمكنك محاولة وضع نقطة توقف على وظيفة open () ومعرفة ما يحدث:

إخراج فائدة Gdb
[root@ivan ~]# gdb -p 23998
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-119.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Attaching to process 23998
… <        debugging symbols...>
...
0x00007f2284c0b20d in poll () at ../sysdeps/unix/syscall-template.S:81
81	T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
Missing separate debuginfos, use: debuginfo-install keyutils-libs-1.5.8-3.el7.x86_64 krb5-libs-1.15.1-34.el7.x86_64 libcom_err-1.42.9-13.el7.x86_64 libgcc-4.8.5-36.el7.x86_64 libselinux-2.5-14.1.el7.x86_64 openssl-libs-1.0.2k-16.el7.x86_64 pcre-8.32-17.el7.x86_64 zlib-1.2.7-18.el7.x86_64
(gdb) set follow-fork-mode child
(gdb) b open
Breakpoint 1 at 0x7f2284c06d20: open. (2 locations)
(gdb) c
Continuing.
[New Thread 0x7f227a165700 (LWP 24030)]
[Switching to Thread 0x7f227a165700 (LWP 24030)]

Breakpoint 1, open64 () at ../sysdeps/unix/syscall-template.S:81
81	T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
(gdb) n
83	T_PSEUDO_END (SYSCALL_SYMBOL)
(gdb) n
_io_FileIO___init___impl (opener=<optimized out>, closefd=<optimized out>, mode=<optimized out>, nameobj=0x7f227a68f6f0, self=0x7f227a68f6c0) at ./Modules/_io/fileio.c:381
381	                Py_END_ALLOW_THREADS
(gdb) n
379	                self->fd = open(name, flags, 0666);
(gdb) n
381	                Py_END_ALLOW_THREADS
(gdb) print name
$1 = 0x7f227a687c90 "/root/test_dir_srv/"
(gdb) q
A debugging session is active.

	Inferior 1 [process 23998] will be detached.

Quit anyway? (y or n) y
Detaching from program: /usr/local/bin/python3.7, process 23998
[Inferior 1 (process 23998) detached]




بعد الأمر c ( متابعة ) ، أطلقت Vanya curl في وحدة تحكم أخرى ، وضربت نقطة توقف في مصحح الأخطاء وبدأت في تنفيذ هذا البرنامج (أي الخدمة) خطوة بخطوة. بمجرد أن وجد اسم مسار مفتوحًا ، قام بطباعة قيمة هذا المتغير ورأى " / root / test_dir_srv / ".

GDB أداة قوية ، وإليك أبسط حالة استخدام. في بعض الأحيان يمكن أن يساعد في إعادة إنتاج أي حالات معقدة (على سبيل المثال ، يمكنك إيقاف العملية مؤقتًا في الوقت المناسب وإعادة إنتاج حالة السباق) ، كما أنه يساعد في قراءة ملفات التفريغ الأساسية.


ماذا لو Docker؟



في مرحلة ما ، قررت DevOps أن الخدمة سيتم نشرها الآن مع حاوية Docker ، وكان من الضروري إعادة اختبار جميع الحالات التي وجدتها Vanya. بحثت Vanya على Google ما يلي دون أي مشاكل:



  1. يمكنك استخدام تشبدومب ، strace و جدب داخل حاوية، ولكن عليك أن نأخذ في الاعتبار قدرات لينكس (هناك مقال يشرح لماذا strace لم تنجح في وعاء دون --cap الإضافة = SYS_PTRACE ).
  2. يمكن استخدام الخيار --pid .


لكنه تساءل عما إذا كان من الممكن رؤية كل حركة المرور تذهب إلى الحاوية (أو من الحاوية) مباشرة من المضيف. في tcpdump ، يمكنك عرض أي واجهة مرور (الخيار -i ) ، كل حاوية تتوافق مع واجهة افتراضية واحدة Veth (يمكن رؤية ذلك ، على سبيل المثال ، من خلال ifconfig أو ip a ) ، ولكن كيف تعرف ما هي الحاوية التي تتوافق معها الواجهة؟ إذا كانت الحاوية لا تستخدم الشبكة المضيفة ، فستكون بداخلها واجهة شبكة eth0 يمكن من خلالها الاتصال عبر الشبكة مع الحاويات الأخرى والمضيف. كل ما تبقى هو العثور على مؤشر iflink للواجهة على المضيف الذي يتطابق مع واجهة iflinketh0 للحاوية (يمكنك قراءة ما يعنيه هذا هنا ).



[root@ivan ~]# for f in `ls /sys/class/net/veth*/ifindex`; do echo $f; cat $f; done | grep -B 1 `docker exec test_service_container cat /sys/class/net/eth0/iflink` | head -1
/sys/class/net/veth6c18dba/ifindex


يمكنك الآن تشغيل tcpdump على واجهة veth6c18dba :



tcpdump -i veth6c18dba


ولكن هناك طريقة أسهل: يمكنك العثور على عنوان IP للحاوية على شبكتها والاستماع إلى حركة المرور عليها:



[root@ivan ~]# docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' test_service_container
172.17.0.10
[root@ivan ~]# tcpdump -i any host 172.17.0.10


الخلاصة: تصحيح الأخطاء في حاوية Docker ليس مشكلة كبيرة. تعمل الأدوات المساعدة فيه ، ويمكنك استخدام سجلات عامل الإرساء لقراءة السجلات .


الاستنتاجات



كمهندس مسؤول ، قررت فانيا أن تحدد بإيجاز معلومات جديدة لنفسها في قاعدة المعرفة الداخلية. هذا ما كتبه:



  • السجلات هي أفضل صديق للرجل. إذا تمت مصادفة سلوك غير متوقع للخدمة وفي نفس الوقت لا تكتب أي شيء إلى السجل ، فهذا سبب لمطالبة المطورين بإضافة سجلات.
  • , , . , Linux , .
  • tcpdump. , .
  • «» strace, ltrace gdb.
  • , Docker-.
  • /proc/PID. , /proc/PID/fd .
  • يمكن أن تساعد الأدوات المساعدة ps و ls و stat و lsof و ss و du و top و free و ip و ldconfig و ldd وغيرها في الحصول على معلومات متنوعة حول النظام أو الملفات أو العمليات .


آمل أن تكون هذه القصة مفيدة لك ، ومرة ​​واحدة على الأقل ستساعدك على فهم ما هو الأمر عند تصحيح شيء ما في Linux. إذا فات فانيا شيئًا ما ، شاركه في التعليقات!



All Articles