Ctrl-C พร้อมกับสองคำสั่งพร้อมกันในทุบตี


15

ฉันต้องการเรียกใช้สองคำสั่งพร้อมกันในทุบตีบนเครื่อง Linux ดังนั้นใน./execute.shทุบตีสคริปต์ของฉันฉันใส่:

command 1 & command 2
echo "done"

อย่างไรก็ตามเมื่อฉันต้องการหยุดสคริปต์ทุบตีและกดCtrl+ Cเฉพาะคำสั่งที่สองเท่านั้นที่หยุด คำสั่งแรกยังคงทำงานอยู่ ฉันจะแน่ใจได้อย่างไรว่าสคริปต์ทุบตีสมบูรณ์หยุดทำงาน หรือไม่ว่าในกรณีใดฉันจะหยุดคำสั่งทั้งสองได้อย่างไร เพราะในกรณีนี้ไม่ว่าฉันจะกดCtrl+ Cคำสั่งที่ทำงานต่อไปบ่อยแค่ไหนและฉันก็ถูกบังคับให้ปิดเทอร์มินัล


สร้างคำถามติดตามเป็นคำถามแยกต่างหากและลบที่นี่ ขณะนี้ยังไม่ชัดเจนสำหรับผู้เข้าชมหากตอบคำถามทั้งคู่หรือเพียงแค่คำถามเริ่มแรก
Zelda

คำตอบ:


17

ถ้าคุณพิมพ์

command 1 & command 2

นี่เท่ากับ

command 1 &
command 2

เช่นนี้จะเรียกใช้คำสั่งแรกในพื้นหลังแล้วเรียกใช้คำสั่งที่สองในเบื้องหน้า โดยเฉพาะอย่างยิ่งหมายความว่าecho "done"พิมพ์ของคุณหลังจากcommand 2เสร็จสิ้นแม้ว่าcommand 1จะยังคงทำงานอยู่

คุณอาจต้องการ

command 1 &
command 2 &
wait
echo "done"

สิ่งนี้จะรันทั้งสองคำสั่งในเบื้องหลังและรอให้ทั้งสองคำสั่งเสร็จสมบูรณ์


หากคุณกด CTRL-C สิ่งนี้จะส่งสัญญาณ SIGINT ไปยังกระบวนการพื้นหน้าเช่นcommand 2ในรุ่นของคุณหรือwaitในเวอร์ชั่นของฉัน

ฉันขอแนะนำให้ตั้งกับดักแบบนี้:

#!/bin/bash

trap killgroup SIGINT

killgroup(){
  echo killing...
  kill 0
}

loop(){
  echo $1
  sleep $1
  loop $1
}

loop 1 &
loop 2 &
wait

ด้วยกับดักสัญญาณ SIGINT ที่ผลิตโดย CTRL-C จะถูกดักจับและแทนที่ด้วยkillgroupฟังก์ชั่นซึ่งจะฆ่ากระบวนการเหล่านั้นทั้งหมด


ขอบคุณสำหรับคำตอบ! อย่างไรก็ตามฉันมีคำถามติดตาม ตอนนี้ฉันมีสคริปต์ต่อไปนี้: กับดัก killgroup SIGINT killgroup () {echo kill ... kill 0} command001 command1 & command2 ฉันลบคำสั่ง wait เนื่องจากสคริปต์ได้รับอนุญาตให้ดำเนินการต่อเมื่อคำสั่งเสร็จสิ้น อย่างไรก็ตามดูเหมือนว่าคำสั่ง 1 จะเริ่มขึ้นเมื่อฉันเรียกใช้สคริปต์ ฉันจะแก้ไขได้ไหม ขอบคุณ
maero21

command1 เริ่มต้นโดยตรงหลังจาก command001 เสร็จสิ้น คุณสามารถใช้set -xที่ด้านบนของสคริปต์เพื่อพิมพ์คำสั่งที่ถูกเรียกใช้งาน
michas

6

เมื่อวางคำสั่งลงในพื้นหลังจากสคริปต์ PID จะไม่ปรากฏบนหน้าจอ คุณสามารถใช้ตัวแปร builtin $!ซึ่งเก็บ PID ของกระบวนการล่าสุดเพื่อให้คุณสามารถจับ PID ของ command1

command1 &
echo $!

จะสะท้อน PID ของ command1

Bash ยังให้กับดักในตัวซึ่งคุณสามารถใช้เพื่อลงทะเบียนลำดับของคำสั่งเพื่อทำงานเมื่อได้รับสัญญาณเฉพาะ คุณสามารถใช้สิ่งนี้เพื่อจับ SIGINT และ kill command1 ก่อนออกจากสคริปต์หลักเช่น

#!/bin/bash

onINT() {
echo "Killing command1 $command1PID too"
kill -INT "$command1PID"
exit
}

trap "onINT" SIGINT
command1 &
command1PID="$!"
comamnd2
echo Done

ขณะที่คำสั่ง 2 กำลังทำงานการกดปุ่มCtrl Cจะทำให้ทั้ง command1 และ command2 ถูกส่ง SIGINT


คุณยังสามารถใช้%nไวยากรณ์เพื่อฆ่างานพื้นหลังที่เฉพาะเจาะจงในเปลือกนี้ โดยปกติแล้วคุณkill %1จะต้องฆ่ากระบวนการพื้นหลังล่าสุดและกระบวนการเดียวเท่านั้น ด้วยกระบวนการพื้นหลังเพิ่มเติมใช้jobsเพื่อดูรายการก่อน
9000

@ 9000: ใช่ แต่ OP กำลังเรียกใช้คำสั่งของพวกเขาในสคริปต์ (./execute.sh) ดังนั้นการได้งานทำมีปัญหามากขึ้นใช่ไหม?

@lain: แน่นอน ฉันพลาดประเด็นเกี่ยวกับการเรียกใช้จากสคริปต์
9000

5

GNU Parallel รุ่นใหม่จะทำสิ่งที่คุณต้องการ:

parallel ::: "command 1" "command 2"
echo "done"

หรือถ้าcommandยังคงเหมือนเดิม:

parallel command ::: 1 2
echo done

ชมวิดีโอแนะนำสำหรับการแนะนำอย่างรวดเร็ว: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

เดินผ่านบทช่วยสอน (ผู้ชาย parallel_tutorial) คุณสั่งบรรทัดด้วยความรักคุณมัน


1

Ctrl+ Cส่งสัญญาณ SIGINT command2ให้กระบวนการด้านหน้าของคุณซึ่งเป็น command1ถูกเรียกใช้ในพื้นหลังดังนั้นจึงไม่เกี่ยวข้องกับอินพุตสตรีม

เมื่อคุณพิมพ์command1 &bash ควรให้ 'PID ของกระบวนการมีลักษณะ[1234]ดังนี้ kill 1234จะฆ่าขั้นตอนนี้คุณสามารถใช้ ตอนนี้ถ้าคุณมี PID ทั้งสองcommand1และcommand2(ดูที่ps -ef) คุณสามารถใช้killเพื่อยกเลิกพวกเขาทั้งหมด:

kill pid1 pid2 pid3 ...

เคล็ดลับเล็กน้อยคือการเรียกใช้คำสั่งทั้งสองในพื้นหลังด้วย:

command1 & command2 &

Bash จะให้ PID ทั้งสองของคุณพร้อมที่จะถูกฆ่า กลอุบายอีกอย่างคือการนำกลับมาcommand1เบื้องหน้าเมื่อคุณฆ่าcommand2:

command1 & command2
# Hit Ctrl+C : command2 terminates.

fg # Bring back command1 to foreground.
# Hit Ctrl+C again, command1 terminates.

ข้อมูลเพิ่มเติมสามารถดูได้ที่นี่: http://linuxg.net/how-to-manage-background-and-foreground-processes/

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