ฉันจะทราบได้อย่างไรว่ากระบวนการใดมีไฟล์ที่เปิดใน Linux


124

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

ดังนั้นฉันจะทราบได้อย่างไรว่ากระบวนการใดมีไฟล์เฉพาะที่เปิดใน Linux โดยเฉพาะอย่างยิ่งชนิดซับเดี่ยวหรือโซลูชันเครื่องมือ Linux ที่เหมาะสมจะดีที่สุด

คำตอบ:


55

คุณยังสามารถใช้fuserสำหรับสิ่งนี้:

~> less .vimrc
# put in background
~> fuser .vimrc
.vimrc:              28135
~> ps 28135
  PID TTY      STAT   TIME COMMAND
28135 pts/36   T      0:00 less .vimrc

มันยอดเยี่ยม แต่การใช้มันในสคริปต์ฉันต้องตรวจสอบความยาวเอาต์พุต
chovy

คุณหมายถึงความยาวของเอาต์พุต
Nathan Fellman

if [ fuser "$ file" `]; จากนั้น exit`
chovy

1
fuser มีพฤติกรรมแปลก ๆ กับรหัสทางออก มันคืนค่า 1 exitcode ที่มีสองสถานะ: A / ข้อผิดพลาดภายในบางไฟล์ที่ตรวจสอบไม่พบ ฯลฯ B / ไม่มีกระบวนการเปิดไฟล์ที่ระบุ ในสถานการณ์ A / ข้อผิดพลาดบางอย่างจะถูกพิมพ์ไปยังเอาท์พุท น่าเสียดายที่เมื่อไฟล์พร้อมใช้งานและเปิดโดยบางสิ่งบางอย่างเอาต์พุตจะถูกสร้างขึ้น แต่ด้วยรหัสการออก 0 มันจะดีกว่าถ้าฟิวเซอร์จะออกด้วยรหัสสามตัว lsoft เป็นการแก้ไขที่แย่กว่านี้เล็กน้อยเนื่องจากทำงานได้ช้ากว่า
Znik

นี่เป็นรูปแบบเดียวกับที่เป็นlsไปตามหลัก - มันจะส่งคืนรหัสออก 2 หากมีข้อผิดพลาด (เช่นระบุตัวเลือกที่ไม่ถูกต้อง) หรือไม่พบไฟล์ (และ 0 หากรายงานข้อมูลสำเร็จ)
สกอตต์

144

ในระบบ Linux ส่วนใหญ่lsof NAMEทำงาน:

fin@r2d2:~$ lsof /home/fin
COMMAND   PID USER   FD   TYPE DEVICE SIZE    NODE NAME
bash    21310  fin  cwd    DIR    8,1 4096 5054467 /home/fin
lsof    21320  fin  cwd    DIR    8,1 4096 5054467 /home/fin
lsof    21321  fin  cwd    DIR    8,1 4096 5054467 /home/fin
fin@r2d2:~$

4
และถ้าคุณไม่มี lsof ล่ะ?
JoseLSegura

3
@JoseLSegura: ฉันคิดว่าคุณมีความรู้เพียงพอสำหรับคำตอบ 'แล้วติดตั้ง lsof' เพื่อจะไร้ประโยชน์สำหรับคุณ คุณสามารถอธิบายปัญหาของคุณได้อย่างละเอียดหรือไม่? หากคุณไม่มีรูทคุณอาจไม่ได้รับข้อมูลส่วนตัวเพื่อดูว่าผู้ใช้รายอื่นเปิดไฟล์ดังกล่าวหรือไม่
Michael Scheper

ดูเหมือนว่านี่จะใช้งานไม่ได้กับไฟล์เฉพาะสำหรับ dirs
Jason

@ Jason: มันใช้งานได้กับไฟล์ แต่cwdบรรทัด (ซึ่งรายงานใช้เป็นไดเรกทอรีการทำงานปัจจุบันของกระบวนการ) เพียงรายงานไดเรกทอรี
reinierpost

9

การเปิดไฟล์ไม่ใช่การล็อคเพราะหากแต่ละกระบวนการต้องตรวจสอบว่าไฟล์เปิดก่อนหรือไม่และดำเนินการต่อว่าเป็นหรือสร้าง / เปิดหากไม่มีหรือไม่กระบวนการทั้งสองสามารถตรวจสอบได้พร้อมกันทั้งคู่ ไม่ได้เปิดจากนั้นทั้งสร้างหรือเปิด

หากต้องการใช้ไฟล์เป็นล็อคการดำเนินการตรวจสอบและล็อคจะต้องมีการดำเนินการแบบต่อเนื่องเดียว คุณสามารถทำสิ่งนี้ได้ในระบบไฟล์ Unix โดยการสร้างไฟล์ด้วยโหมดอ่านอย่างเดียวและลบออกเพื่อปลดล็อก หากไฟล์มีอยู่ (และอ่านอย่างเดียว) การสร้างไฟล์จะล้มเหลวดังนั้นคุณจะได้รับการตรวจสอบและล็อคในการทำงานแบบปรมาณูเดียว

หากกระบวนการล็อคของคุณเป็นเชลล์สคริปต์ที่จะทำงานเป็น daemon คุณสามารถได้รับผลกระทบนี้โดยใช้umaskการตั้งค่าต่อกระบวนการที่กำหนดสิทธิ์ที่สร้างไฟล์ใหม่ด้วย:

oldumask = $ (umask)
umask 222 # สร้างไฟล์ที่ไม่สามารถเขียนให้เจ้าของได้เช่นกัน
ถ้า echo $$> / var / lock / foo
แล้วก็
    : การล็อคสำเร็จ
อื่น
    : การล็อคล้มเหลว
Fi
ขอ $ oldumask
นอกจากนี้ยังเขียน PID ของกระบวนการที่เป็นเจ้าของลงในไฟล์ซึ่งแก้ไขปัญหาอื่นของคุณ: cat /var/lock/foo
สำหรับคำถามเฉพาะ "กระบวนการใดที่ไฟล์นี้เปิดอยู่" นี่เป็นประโยชน์เมื่อคุณต้องการยกเลิกการต่อเชื่อมระบบไฟล์ แต่ไม่สามารถทำได้เนื่องจากบางกระบวนการมีไฟล์เปิดอยู่ หากคุณไม่มีคำสั่งเหล่านั้นคุณสามารถถาม/procในฐานะรูท:

ls -l /proc/*/cwd | grep '/var/lock/foo$'

หรือในฐานะผู้ใช้ที่เป็นมนุษย์:

ls -l /proc/*/cwd 2>/dev/null | grep '/var/lock/foo$'


วิธี `ls -l 'ใช้งานได้กับ Linux แต่ดูเหมือนจะไม่ทำงานกับ CygWin: ไม่มีข้อมูลเกี่ยวกับการล็อกไฟล์ที่นั่น คุณไม่ทราบวิธีแก้ปัญหาเหรอ? ขอบคุณ
Sopalajo de Arrierez

ไม่คุณไม่ได้สร้างไฟล์แบบอ่านอย่างเดียวสำหรับการล็อกเนื่องจากเมื่อแอปของคุณเกิดขัดข้องไฟล์จะยังคงอยู่ที่นั่น การบังคับให้ผู้ใช้ล้างข้อมูลอึหลังจากแอปที่คุณใช้งานไม่ได้
polkovnikov.ph

6

หากคุณต้องการทราบว่าตัวบ่งชี้ไฟล์ของกระบวนการที่แน่นอนลิงก์ไปยังไฟล์ของคุณโดยไม่มีlsofหรือfuser- ค้นหาผ่าน/proc:

$ find /proc -regex '\/proc\/[0-9]+\/fd\/.*' -type l -lname "*$1*" -printf "%p -> %l\n" 2> /dev/null

แทนที่$1ด้วยชื่อไฟล์เปิดที่คุณกำลังค้นหา คุณสามารถแก้ไข-printfสิ่งที่คุณต้องการดูหรือไพพ์egrep -o '[0-9]+' | head -1เพื่อใช้กับข้อมูลของกระบวนการนั้นps -Fp <pid>

คำตอบโดย @fin เป็นคำตอบที่ดีที่สุดอย่างเห็นได้ชัด แต่จะตอบ@ ความคิดเห็นของ JoseLSeguraถ้านี้ไม่สามารถแก้ปัญหาดังกล่าวข้างต้นคือคำตอบของฉัน$ lsof <filename>


2

ฉันพบว่าการใช้คำตอบที่ยอมรับไม่ได้แสดงรายการกระบวนการที่ใช้ไดเรกทอรีของฉัน (Ubuntu 14.04)

ในตอนท้ายฉันใช้ lsof (แสดงรายการไฟล์ที่เปิด) และเอาท์พุทของมันเพื่อค้นหากระบวนการที่ผิด:

lsof | egrep "<regexp-for-your-file>"

วิธีทำความสะอาดมากขึ้นและเร็วขึ้นสำหรับการใช้งานนี้เป็นตัวเลือกของlsof -Rเช่น: lsof -R [filename]
tron5
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.