ฆ่าหลายอินสแตนซ์ของกระบวนการทำงานด้วยคำสั่งเดียว


75

สมมติว่าฉันมีหนึ่งพันหรือมากกว่าอินสแตนซ์ของกระบวนการใด ๆ (ตัวอย่างเช่นvi) ทำงาน ฉันจะฆ่าพวกเขาทั้งหมดในหนึ่งนัดเดียว / คำสั่งหนึ่งบรรทัด / คำสั่งเดียวได้อย่างไร


3
มันไม่ชัดเจนว่าระบบที่คุณตั้งใจจะทำงานนี้ ตัวอย่างเช่นบน Linux ฉันใช้pkillจากprocpsแพ็คเกจ
Deer Hunter

คำถามถูกถามจากมุมมองทั่วไป ฉันรู้เพียงสองกระบวนการเช่น killall และผ่าน awk / sed แต่ฉันอยากรู้ว่ามีวิธีอื่นในการบรรลุเป้าหมายนี้หรือไม่ หากมีการทำแตกต่างกันในระบบที่แตกต่างกันแล้วฉันต้องการที่จะรู้ว่าสิ่งที่ มันเป็นเรื่องยุ่งยากมากสำหรับ google แทนที่จะคิดว่าจะคุยกับพวกคุณทุกคน
The Dark Knight

คำตอบ:


97

มีอะไรผิดปกติกับคนดี

for pid in $(ps -ef | grep "some search" | awk '{print $2}'); do kill -9 $pid; done

มีวิธีที่จะทำให้มันมีประสิทธิภาพมากขึ้น

for pid in $(ps -ef | awk '/some search/ {print $2}'); do kill -9 $pid; done

และรูปแบบอื่น ๆ แต่ในระดับพื้นฐานมันใช้งานได้สำหรับฉันเสมอ


1
โหวตขึ้นรู้เกี่ยวกับรูปแบบแรกเท่านั้น ครั้งที่สองดูมีประสิทธิภาพมากขึ้นขอบคุณ
The Dark Knight

5
@TheDarkKnight ปัญหาเกี่ยวกับวิธีการนี้คือคุณมักจะต้องฆ่ามากกว่าที่คุณตั้งใจ การเขียน "การค้นหาบางอย่าง" ที่เชื่อถือได้นั้นค่อนข้างยุ่งยาก ภายใต้ Linux ให้ใช้ pkillซึ่งจัดการกับ subtleties ส่วนใหญ่
Gilles

ฉันไม่แน่ใจว่ามันเป็นเรื่องยากหากคุณกำลังตรวจสอบไบนารีที่แน่นอนมันน่าเชื่อถือ ฉันมักจะเรียกใช้มันเป็นecho kill -9 $pidครั้งแรกอยู่แล้วเพื่อให้ฉันรู้ว่าสิ่งที่ฉันได้รับ ฉันไม่แน่ใจว่า AIX มีpkillซึ่งเป็นขนมปังและเนย UNIX ของฉัน และมันก็แย่มากพอที่จะลงคะแนน - แปลก
EightBitTony

1
ถ้าไม่จำเป็นจริงๆคุณควรส่งกระบวนการ SIGTERM แทน SIGKILL

ฉันควรจะเพิ่มว่าวิธีการทั้งสองนี้จะไม่ทำงานในทุกเชลล์ตัวอย่างเช่นมันจะไม่ทำงานcsh
non sequitor

38

ใช้ killall

killall vi

นี้จะฆ่าคำสั่งทั้งหมดชื่อ 'vi'

คุณอาจเพิ่มสัญญาณได้เช่นกันเช่น SIGKILL

killall -9 vi


ถูกต้องแล้วคุณยังสามารถเพิ่มสัญญาณที่คุณต้องการเช่นkillall -9 vi
Hola Soy Edu Feliz Navidad

1
ฉันไม่คิดว่า killall เป็น naswer ของมัน: การฆ่าโดยไฟล์จะใช้งานได้สำหรับไฟล์ปฏิบัติการที่เปิดไว้ระหว่างการประมวลผลเท่านั้นเช่นไฟล์เอ็กซีคิวต์ไม่สามารถฆ่าได้ด้วยวิธีนี้ การพิมพ์ชื่อ killall อาจไม่ส่งผลที่ต้องการในระบบที่ไม่ใช่ Linux โดยเฉพาะอย่างยิ่งเมื่อทำโดยผู้ใช้ที่มีสิทธิพิเศษถ้าฉันพยายามลบอินสแตนซ์ของกระบวนการที่ไม่ใช่ลินุกซ์จำนวนมาก killall -w ตรวจไม่พบว่ากระบวนการหายไปและถูกแทนที่ด้วยกระบวนการใหม่ด้วย PID เดียวกันระหว่างการสแกน หากกระบวนการเปลี่ยนชื่อพวกเขา killall อาจไม่สามารถจับคู่พวกเขาได้อย่างถูกต้อง
The Dark Knight

13
โปรดทราบว่านี่ใช้ได้กับ Linux และ BSD เท่านั้น บน Solaris และระบบอื่น ๆkillallทำสิ่งที่ชื่อแนะนำ ... มันฆ่ากระบวนการเริ่มต้น
Bobby

2
บน AIX มัน "ยกเลิกกระบวนการทั้งหมดที่คุณเริ่มต้นยกเว้นกระบวนการที่สร้างกระบวนการ killall"
EightBitTony

31

pkillเป็นสิ่งที่ฉันแนะนำถ้ามี ( Linux , FreeBSD , NetBSD , OpenBSD , Solaris ) คุณสามารถระบุกระบวนการตามชื่อคำสั่งโดยบรรทัดคำสั่งแบบเต็มหรือเกณฑ์อื่น ๆ ยกตัวอย่างเช่นฆ่าโปรแกรมทั้งหมดที่มีชื่อคำสั่งมีอักขระย่อยpkill vi viเพื่อฆ่ากระบวนการที่เรียกว่าviใช้pkill -x viเท่านั้น เพื่อฆ่ากระบวนการเฉพาะที่เรียกว่าviมีอาร์กิวเมนต์สุดท้ายสิ้นสุดในการใช้งาน.confpkill -fx 'vi.*\.conf'

หากต้องการดูรายการ PID ที่pkillจะส่งสัญญาณให้ใช้pgrepซึ่งมีรูปแบบเหมือนกันทุกประการยกเว้นว่าจะไม่ยอมรับชื่อสัญญาณหรือหมายเลข หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับกระบวนการเหล่านี้ให้เรียกใช้

ps -p "$(pgrep …)"

ภายใต้ Linux คุณต้องการps -p $(pgrep -d, …)แทน (นั่นเป็นข้อผิดพลาด: Linux psไม่เข้ากับ POSIX)

อีกวิธีทั่วไปในการระบุกระบวนการที่จะฆ่าคือกระบวนการที่มีไฟล์เปิดอยู่ (ซึ่งสามารถปฏิบัติการได้ของกระบวนการ) คุณสามารถแสดงรายการเหล่านี้ด้วยfuser; ใช้fuser -kสำหรับส่งสัญญาณ ตัวอย่างเช่นการfuser -k /usr/bin/findฆ่าทั้งหมดที่ทำงานอยู่findนั้นไม่ใช่

หากมีกระบวนการที่ต้องหลบหนีคุณจะต้องฆ่ากลุ่มกระบวนการทั้งหมดในครั้งเดียว กลุ่มกระบวนการถูกระบุโดยค่าลบของผู้นำซึ่งเป็นกระบวนการบรรพบุรุษของกระบวนการทั้งหมดในกลุ่ม หากต้องการดูกลุ่มกระบวนการที่เป็นของกระบวนการให้เรียกใช้ps -o pgid(รวมถึงตัวเลือกใด ๆ เพื่อเลือกกระบวนการที่จะแสดง) หากคุณพิจารณาว่าคุณต้องการฆ่าหัวหน้ากลุ่มกระบวนการ 1234 และลูก ๆ ของกลุ่มทั้งหมดให้รันkill -1234หรือkill -HUP -1234หรือสัญญาณอื่น ๆ

หากคุณไม่พบวิธีที่ดีกว่าให้ใช้psกับตัวเลือกที่เหมาะสมเพื่อแสดงรายการกระบวนการทั้งหมดและกรองด้วยgrepหรือคำสั่งการกรองข้อความอื่น ๆ ระวังอย่าจับคู่กระบวนการอื่นที่บังเอิญใช้คำสั่งด้วยชื่อที่คล้ายกันโดยไม่ตั้งใจหรือด้วยอาร์กิวเมนต์ที่มีชื่อนั้น ตัวอย่างเช่น:

kill $(ps -o pid -o comm | awk '$2 == "vi" {print $1}')

โปรดจำไว้ว่าคำสั่งgrepหรือawkคำสั่งของคุณอาจแสดงอยู่ในpsเอาต์พุต ( psและคำสั่งการกรองจะเริ่มต้นพร้อมกันดังนั้นไม่ว่ามันจะปรากฏขึ้นหรือไม่ขึ้นอยู่กับเวลา) นี่เป็นสิ่งสำคัญอย่างยิ่งหากอาร์กิวเมนต์คำสั่งรวมอยู่ในpsเอาต์พุต


ขอบคุณมากนี่มันยอดเยี่ยมจริงๆ สิ่งที่คุณได้รับคือการสอนแบบหนึ่ง ขอบคุณอีกครั้ง . โหวตขึ้น
The Dark Knight

6

pkillดีมากที่นี่ คุณสามารถให้พารามิเตอร์จำนวนมากเพื่อปรับแต่งรูปแบบ


ไม่สามารถใช้ได้กับ UNIX ทั้งหมดและไม่มีการกล่าวถึงระบบปฏิบัติการ UNIX หรือ UNIX ที่มีลักษณะเฉพาะในคำถาม
EightBitTony

@EightBitTony pkillให้บริการบน Linux, BSD และ Solaris - afaik killallดังนั้นจึงมีการแพร่กระจายมีขนาดใหญ่กว่า
นิลส์

ฉันเห็นด้วย แต่ killall เป็นปัญหามากขึ้นเพราะมีเครื่องมือหลายอย่างที่มีชื่อเดียวกันซึ่งมีพฤติกรรมแตกต่างกันอย่างมากที่ดูเหมือน ฉันไม่ชอบคำตอบของ killall เช่นกัน pkill ไม่มีอยู่บน AIX หรือ HP-UX และแม้ว่าบางคนชอบที่จะเชื่อ แต่ก็ยังคงมีความสำคัญอยู่บนพื้นฐานของ non-Linux UNIX ในโลก
EightBitTony

1
@EightBitTony นั่นคือเหตุผลที่คำตอบของคุณคือคำตอบที่ยอมรับได้ แต่ฉันจะไม่ใช้มันกับ Solaris (ซึ่งก็คือ Unix ด้วย)
นิลส์

6

วิธีที่ง่ายที่สุดคือตรวจสอบก่อนว่าคุณได้รับรหัสกระบวนการที่ถูกต้องด้วย:

pgrep -f [part_of_a_command]

หากผลเป็นไปตามที่คาดไว้ ไปกับ:

pkill -f [part_of_a_command]

หรือใช้:pgrep -f "command name"
Magne

3

ไม่มีใครพูดถึงสิ่งนี้ที่น่าสนใจ pidofเอาต์พุต pids ที่คั่นด้วยช่องว่างของกระบวนการที่ตรงกับชื่อกระบวนการที่ส่งผ่าน คุณสามารถใช้เอาต์พุตโดยตรงkillโดยไม่ต้องมีpiping บน Arch Linux ฉันใช้

kill -9 $(pidof <proc name>)

ข้อเสียของโซลูชันนี้คือไม่อนุญาตให้ใช้นิพจน์ทั่วไป


0

pkillผมขอแนะนำให้คุณลอง

Ex: ps -ef | pkill -f command

หากต้องการแสดงรายการของกระบวนการทั้งหมดที่จะฆ่าก่อนลองpgrep:

Ex: ps -ef | pgrep -f command


1
อะไรคือจุดประสงค์ของการส่งออกps -efไปยังpkillหรือท่อpgrep? คำสั่งเหล่านี้ไม่ได้อ่านจากอินพุตมาตรฐาน
Kusalananda

0

คุณสามารถฆ่ากระบวนการต่าง ๆ ได้หลายอย่างโดยใช้คำสั่งด้านล่าง

pkill -9 -f "\.\/.+\s\.|process1|process2|process3\[^"

โปรดทราบว่านี่จะฆ่ากระบวนการที่ตรงกับรูปแบบข้างต้นซึ่งหมายความว่าprocess1abc process2def process3ghiจะได้รับการฆ่าด้วย


-1

pgrep "name-of-application" | xargs kill -9

ง่ายพอที่จะจดจำและทำงานได้ดีสำหรับฉัน



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