ซ็อกเก็ตที่พบโดย lsof แต่ไม่ใช่โดย netstat


19

ฉันมีแอปพลิเคชั่นที่ไม่มีตัวให้คำอธิบายไฟล์ปรากฏอยู่โดยเปิดซ็อกเก็ต แต่ฉันไม่สามารถหาได้ว่าซ็อกเก็ตเหล่านี้ทำอะไร เหล่านี้ปรากฏในผลลัพธ์ lsof เป็น

java    9689 appuser 1010u  sock       0,5          263746675 can't identify protocol
java    9689 appuser 1011u  sock       0,5          263746676 can't identify protocol
java    9689 appuser 1012u  sock       0,5          263746677 can't identify protocol
java    9689 appuser 1014u  sock       0,5          263746678 can't identify protocol
java    9689 appuser 1015u  sock       0,5          263746679 can't identify protocol
java    9689 appuser 1016u  sock       0,5          263746681 can't identify protocol

และใน / proc / $ PID / fd เป็น

lrwx------ 1 appuser appuser 64 Jun 23 11:49 990 -> socket:[263732085]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 991 -> socket:[263732086]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 992 -> socket:[263735307]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 993 -> socket:[263732088]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 995 -> socket:[263735308]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 996 -> socket:[263735309]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 997 -> socket:[263745434]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 998 -> socket:[263745435]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 999 -> socket:[263745436]

netstat -aแต่ไม่มีการส่งออกที่คล้ายกันใน

ซ็อกเก็ตเหล่านี้คืออะไรและฉันจะทราบได้อย่างไรว่าพวกเขาทำอะไร

แก้ไข : ฉันได้ลองใช้งานgrep $SOCKET /proc/netตามที่แนะนำใน lsof FAQโดยที่ $ SOCKET เป็นอินสแตนซ์ 263746679 แต่นั่นก็ไม่ได้ผลลัพธ์


ในฐานะที่เป็นพื้นหลังแอปพลิเคชั่นเป็นที่เก็บของสำหรับงานหลายอย่าง ฉันต้องแยกออกเป็นชิ้น ๆ ที่บ้าดีเดือด แต่จนกระทั่งฉันพบว่าซ็อกเก็ตเหล่านั้นสื่อสารกับใครฉันติดอยู่


เรากำลังเผชิญกับปัญหานี้เมื่อเร็ว ๆ นี้ด้วยหนึ่งในเว็บแอป. NET Core ของเรา (เซิร์ฟเวอร์ Ubuntu กับ Kestrel) แต่อุปกรณ์ที่บันทึกไว้คือ "0,9" ด้วยชื่อ "โปรโตคอล: TCP" พยายามค้นหาว่าอุปกรณ์ 0 และ 9 ใดที่พิสูจน์แล้วว่าเป็นเรื่องยาก แต่อาการต่าง ๆ จะรู้สึกเหมือนเปิดซ็อกเก็ตเดียวกันโดยไม่มีข้อผูกมัดและใช้มัน
icelava

คำตอบ:


17

สิ่งนี้สามารถเกิดขึ้นได้หากคุณสร้างซ็อกเก็ต แต่ไม่เคยเชื่อมต่อ () หรือผูก () ด้วย ทางออกที่ดีที่สุดของคุณคือ strace (-fF) แอปพลิเคชันจากนั้นจึงอ้างอิงข้ามกับเอาต์พุตของ lsof เพื่อพิจารณาว่าซ็อกเก็ตใดที่ทำให้เกิดปัญหา เป็นวิธีโบนัสในการดีบั๊ก: ถ้าคุณตัดการเรียกซ็อกเก็ตของคุณด้วยข้อมูลการดีบักและเขียนออกไปที่ / dev / null มันจะปรากฏใน strace โดยไม่ให้ไฟล์บันทึกที่มีขนาดใหญ่มาก


ขอขอบคุณมันฟังดูน่าสนใจ ฉันจะพยายามดูว่าเป็นกรณีของใบสมัครของเราหรือไม่
Robert Munteanu

1
ค่อนข้างตามบรรทัดเดียวกันเพราะนี่คือ Java อาจเป็นเรื่องยากมากที่จะใช้ strace; วิธีที่ดีกว่าอาจสร้างซ็อกเก็ตคลาสย่อยของคุณเองซึ่งบันทึกข้อมูลก่อนส่งผ่านไปยังซ็อกเก็ต JDK พาเรนต์ (จริง) strace สามารถเห็นการเรียก Java พื้นฐานไปยังระบบปฏิบัติการเท่านั้นและไม่สามารถมองเห็นภายในเธรดของคุณสำหรับสิ่งที่ทำให้การเรียกใช้ซ็อกเก็ตเหล่านั้นเพื่อที่จะ strace มันทั้งหมดดูเหมือนว่า java ลูกใหญ่ตัวหนึ่ง
troyengel

@troyengel: ฉันได้ค้นพบ Byteman ( jboss.org/byteman ) อีกครั้งซึ่งเป็นเครื่องมือที่เรียบร้อยมากซึ่งทำให้ฉันสามารถฉีดรหัสไบต์ที่จำเป็นในการติดตามการโทรเหล่านี้ได้
Robert Munteanu

คำตอบที่มีประโยชน์ที่สุดดังนั้นนี่จึงเป็นรางวัล ขอบคุณ!
Robert Munteanu

2

เมื่อใช้ Python ฉันพบปัญหาเดียวกันกับซ็อกเก็ต SSL:

  • เมื่อฉันใช้ socket.close () ซ็อกเก็ตยังคงอยู่ในสถานะ CLOSE_WAIT เป็นเวลาไม่ จำกัด
  • เมื่อฉันใช้ socket.shutdown () lsof พูดว่า "ไม่สามารถระบุโปรโตคอล"

ทางออกคือการแกะเลเยอร์ SSL ก่อนปิด:

  • origsock = socket.unwrap ()
  • origsock.close ()

นี่เป็นการปิดซ็อกเก็ตอย่างเหมาะสมในแอพของฉัน


1

สิ่งแรกที่ฉันจะทำคือเพิ่มถ้าขีด จำกัด ตัวอธิบายไฟล์ของคุณ:

~# vi /etc/sysctl.conf
fs.file-max = 331287

ต่อไปฉันจะตรวจสอบให้แน่ใจว่าระบบของคุณทันสมัยแล้วซึ่งรวมถึงไลบรารีและเซิร์ฟเวอร์ทั้งหมด อาจเป็นไปได้ว่าเซิร์ฟเวอร์แอปพลิเคชัน Java ของคุณล้าสมัย (หากคุณใช้) นอกจากนี้ยังมีความเป็นไปได้ที่แอปพลิเคชันเซิร์ฟเวอร์ของคุณจะถูกกำหนดค่าผิดพลาดคุณควรดูที่ไฟล์กำหนดค่าของคุณและลดระดับconnectionTimeoutและ / หรือของคุณลงmaxKeepAliveRequests(ฉันไม่แน่ใจว่าแอพพลิเคชันเซิร์ฟเวอร์ของคุณกำลังใช้งานอยู่หรือไม่

ฉันไม่แน่ใจว่าแอปพลิเคชั่นนี้ทำอะไร แต่ถ้าคุณไม่คิดว่ามันต้องใช้ซ็อกเก็ตนับหมื่นซ็อกเก็ตนี่ก็เกือบจะเป็น"ตัวบ่งชี้ไฟล์รั่วไหล"ในแอปพลิเคชัน Java ของคุณ คุณอาจต้องส่งรายงานข้อผิดพลาดไปยังผู้ขาย ในรายงานข้อผิดพลาดนี้คุณควรรวมข้อมูลเกี่ยวกับวิธีการสร้างปัญหาขึ้นใหม่

ต่อไปนี้เป็นวิธีแก้ไขข้อบกพร่องของปัญหา

Wireshark (หรือ twireshark สำหรับ cli) เป็นเครื่องมือที่ดีที่สุดเพื่อดูว่ามีการใช้ซ็อกเก็ตเหล่านี้อย่างไร Wireshark จะให้คุณแยกประเภทของการจราจรที่ถูกโยนข้ามลวด เป็นไปได้ว่าการเชื่อมต่อสองสามครั้งแรกจะประสบความสำเร็จจากนั้นจะถึงขีด จำกัด ตัวอธิบายไฟล์ เมื่อขีด จำกัด ตัวอธิบายไฟล์ถูกโจมตี Wireshark จะไม่ไปรับสิ่งใด (และ neater เป็น netstat สำหรับเรื่องนั้น) แต่สิ่งนี้จะช่วย จำกัด ปัญหาให้แคบลง อาจมีกรณีที่มีการส่งออก SYN จำนวนมาก แต่ไม่มีการรับ SYN / ACKs ดังนั้นการเชื่อมต่อ tcp จำนวนมากจึงติดอยู่ในสถานะ SYN_WAIT

หากคุณมีการเข้าถึงซอร์สโค้ดและคุณรู้ประเภทของซ็อกเก็ตที่ถูกสร้างขึ้น (เช่นการใช้ strace หรือเพียงแค่ค้นหารหัส) จากนั้นคุณสามารถเปิดโครงการใน Eclipse (หรือ IDE อื่น) และตั้งจุดพักที่ฟังก์ชันที่ กำลังสร้างซ็อกเก็ตเหล่านี้ เมื่อเบรกพอยต์โดนกระทบคุณสามารถดูการติดตามสแต็กได้ ไฟล์ descriptor นี้รั่วได้อาจเป็น infinite loop หรือค่า timeout ของ socket นั้นใหญ่เกินไป ความเป็นไปได้อีกอย่างหนึ่งคือแอป java ไม่ได้ทำการsocket.close()ล้างข้อมูลการเชื่อมต่อ การปิดจะกระทำโดยทั่วไปในfinelyบล็อกของ a try/catch(ใช่ซ็อกเก็ตต้องมีการลอง / จับใน Java เสมอมิเช่นนั้นจะไม่สร้าง :) ในตอนท้ายของวันมีแนวโน้มว่าแอป Java ไม่จัดการ IOException อย่างถูกต้อง


ขอบคุณสำหรับคำตอบ. ฉันกำลังพัฒนาแอปพลิเคชันนี้จริง ๆ - ส่วนคอนเทนเนอร์ - แทนที่จะจัดการมันและฉันไม่สามารถพบปัญหาใด ๆ ที่เกี่ยวข้องกับซ็อกเก็ตที่ไม่ได้ปิด แต่คำใบ้ของ wireshark / twireshark นั้นดีฉันจะใช้มัน
Robert Munteanu

@Robert Munteanu หากคุณกำลังสร้างแอพนี้ thenthis เป็นคำถามสำหรับ stackoverflow ไม่น้อยที่คุณกำลังเปิดซ็อกเก็ตมากเกินไป
โกง

Rook: ฉันยอมแพ้ในการค้นหาโค้ดที่ชาญฉลาดนี้และพยายามติดตามมันเป็นระบบดูแลระบบ นั่นเป็นเหตุผลที่ฉันโพสต์บน SF และใช่ฉันรู้ว่าซ็อกเก็ตมากเกินไปเปิดอยู่ แต่มีเบาะแสศูนย์เป็นที่ที่ ...
โรเบิร์ต Munteanu

@Robert Munteanu คุณต้องตั้งจุดพักตามการสร้างซ็อกเก็ตและดูที่การติดตามสแต็กและหน่วยความจำ ณ จุดนั้น ฉันสงสัยว่าคุณกำลังตกอยู่ในวงวนไม่ จำกัด ความสามารถในการดูตัวแปรและขั้นตอนต่าง ๆ แม้ว่ารหัสของคุณจะเป็นวิธีที่ดีที่สุดสำหรับปัญหาที่ซับซ้อนเช่นนี้
โกง

Rook โชคไม่ดีที่สิ่งนี้เกิดขึ้นแบบสุ่มบนเซิร์ฟเวอร์หนึ่งใน 20 เซิร์ฟเวอร์ - ไม่เหมือนกันเสมอ - เฉพาะในสภาพแวดล้อมการผลิตและอาจสองครั้งต่อสัปดาห์ ไม่อย่างนั้นมันก็ค่อนข้างง่ายที่จะใช้นิ้วชี้ ขณะนี้ฉันใช้ Byteman ( jboss.org/byteman ) เพื่อติดตามการสร้างซ็อกเก็ต / ผูก / เชื่อมต่อ / ปิดการโทร หวังว่าบางสิ่งจะออกมาจากมัน
Robert Munteanu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.