ไม่สามารถหยุดสคริปต์ทุบตีด้วย Ctrl + C


42

ฉันเขียนสคริปต์ทุบตีง่าย ๆ ด้วยวนสำหรับพิมพ์วันที่และ ping ไปยังเครื่องระยะไกล:

#!/bin/bash
while true; do
    #     *** DATE: Thu Sep 17 10:17:50 CEST 2015  ***
    echo -e "\n*** DATE:" `date` " ***";
    echo "********************************************"
    ping -c5 $1;
done

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

MacAir:~ tomas$ ping-tester.bash www.google.com

*** DATE: Thu Sep 17 23:58:42 CEST 2015  ***
********************************************
PING www.google.com (216.58.211.228): 56 data bytes
64 bytes from 216.58.211.228: icmp_seq=0 ttl=55 time=39.195 ms
64 bytes from 216.58.211.228: icmp_seq=1 ttl=55 time=37.759 ms
^C                                                          <= That is Ctrl+C press
--- www.google.com ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 40.887/59.699/78.510/18.812 ms

*** DATE: Thu Sep 17 23:58:48 CEST 2015  ***
********************************************
PING www.google.com (216.58.211.196): 56 data bytes
64 bytes from 216.58.211.196: icmp_seq=0 ttl=55 time=37.460 ms
64 bytes from 216.58.211.196: icmp_seq=1 ttl=55 time=37.371 ms

ไม่ว่าฉันจะกดกี่ครั้งหรือเร็วแค่ไหนก็ตาม ฉันไม่สามารถหยุดมันได้
ทำแบบทดสอบและรับรู้ด้วยตัวเอง

เป็นวิธีแก้ปัญหาด้านฉันกำลังหยุดมันด้วยที่จะหยุดมันแล้วCtrl+Zkill %1

เกิดอะไรขึ้นที่นี่ด้วย^C?

คำตอบ:


26

สิ่งที่เกิดขึ้นคือการที่ทั้งสองbashและpingได้รับ SIGINT ( bashเป็นไม่โต้ตอบทั้งสองpingและการbashทำงานในกระบวนการกลุ่มเดียวกันซึ่งได้รับการสร้างขึ้นและตั้งเป็นกลุ่มกระบวนการเบื้องหน้าของสถานีโดยเปลือกโต้ตอบคุณวิ่งจากสคริปต์ที่)

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

$ bash -c 'sh -c "trap exit\ 0 INT; sleep 10; :"; echo here'
^Chere

ข้างต้นbash, shและsleepได้รับ SIGINT เมื่อกด Ctrl-C แต่shออกได้ตามปกติด้วยรหัส 0 ทางออกเพื่อbashละเว้น SIGINT ซึ่งเป็นเหตุผลที่เราเห็น "ที่นี่"

pingอย่างน้อยหนึ่งตัวจาก iputils ก็เป็นแบบนั้น เมื่อถูกขัดจังหวะมันจะพิมพ์สถิติและออกด้วยสถานะทางออก 0 หรือ 1 ขึ้นอยู่กับว่ามีการตอบปิงหรือไม่ ดังนั้นเมื่อคุณกด Ctrl-C ขณะที่pingกำลังทำงานอยู่โปรดbashทราบว่าคุณได้กดCtrl-Cตัวจัดการ SIGINT แต่เนื่องจากการpingออกตามปกติbashจะไม่ออก

หากคุณเพิ่ม a sleep 1ในลูปนั้นและกดCtrl-Cขณะที่sleepกำลังทำงานเนื่องจากsleepไม่มีตัวจัดการพิเศษบน SIGINT มันจะตายและรายงานbashว่ามันตายจาก SIGINT และในกรณีbashนั้นจะออก (จริง ๆ แล้วจะฆ่าตัวเองด้วย SIGINT เพื่อ เพื่อรายงานการหยุดชะงักของผู้ปกครอง)

สำหรับสาเหตุที่เป็นbashเช่นนั้นฉันไม่แน่ใจและฉันทราบว่าพฤติกรรมนั้นไม่ได้กำหนดไว้ล่วงหน้าเสมอไป ฉันเพิ่งถามคำถามเกี่ยวกับbashรายชื่อรับจดหมายข่าวเพื่อการพัฒนา ( อัปเดต : @Jilles ได้ย้ำเหตุผลในคำตอบของเขาไว้แล้ว)

เชลล์อื่น ๆ ที่ฉันพบว่ามีพฤติกรรมคล้ายกันคือ ksh93 (อัปเดตตามที่ @Jilles พูดถึงเช่น FreeBSDsh ) ดูเหมือนว่า SIGINT จะถูกเพิกเฉยอย่างชัดเจน และksh93ออกเมื่อใดก็ตามที่คำสั่งถูกฆ่าโดย SIGINT

คุณได้รับพฤติกรรมเช่นเดียวกับbashข้างต้น แต่ยัง:

ksh -c 'sh -c "kill -INT \$\$"; echo test'

ไม่ส่งออก "ทดสอบ" นั่นคือมันจะออก (โดยการฆ่าตัวเองพร้อมกับ SIGINT ที่นั่น) หากคำสั่งที่กำลังรอการตายของ SIGINT แม้ว่ามันจะไม่ได้รับ SIGINT นั้นก็ตาม

การหลีกเลี่ยงจะเพิ่ม:

trap 'exit 130' INT

ที่ด้านบนของสคริปต์เพื่อบังคับbashให้ออกเมื่อได้รับ SIGINT (โปรดทราบว่าในกรณีใด ๆ SIGINT จะไม่ถูกประมวลผลแบบซิงโครนัสเฉพาะหลังจากที่คำสั่งที่รันอยู่ในปัจจุบันได้ออกไปแล้ว)

ตามหลักการแล้วเราต้องการรายงานไปยังผู้ปกครองของเราว่าเราเสียชีวิตจาก SIGINT (ดังนั้นหากเป็นbashสคริปต์อื่นเช่นbashสคริปต์นั้นก็จะถูกขัดจังหวะด้วย) การทำแบบexit 130นี้ไม่เหมือนกับการตายของ SIGINT (แม้ว่ากระสุนบางตัวจะตั้งค่า$?เป็นค่าเดียวกันสำหรับทั้งสองกรณี) แต่ก็มักจะใช้เพื่อรายงานการตายโดย SIGINT (ในระบบที่ SIGINT เป็น 2 ซึ่งมากที่สุด)

อย่างไรก็ตามสำหรับbash, ksh93หรือ FreeBSD shที่ไม่ได้ทำงาน สถานะทางออก 130 รายการนั้นไม่ถือเป็นความตายโดย SIGINT และสคริปต์หลักจะไม่ยกเลิกที่นั่น

ดังนั้นทางเลือกที่ดีกว่าน่าจะเป็นการฆ่าตัวเราเองด้วย SIGINT เมื่อได้รับ SIGINT:

trap '
  trap - INT # restore default INT handler
  kill -s INT "$$"
' INT

1
คำตอบของ jillesอธิบายว่า "ทำไม" ในฐานะที่เป็นตัวอย่างfor f in *.txt; do vi "$f"; cp "$f" newdir; doneเช่นพิจารณา  หากผู้ใช้พิมพ์ Ctrl + C ในขณะที่แก้ไขไฟล์ใดไฟล์หนึ่งviเพียงแค่แสดงข้อความ ดูเหมือนว่าการวนซ้ำควรดำเนินการต่อหลังจากผู้ใช้แก้ไขไฟล์เสร็จ (และใช่ฉันรู้ว่าคุณสามารถพูดได้vi *.txt; cp *.txt newdirฉันแค่ส่งforลูปเป็นตัวอย่าง)
Scott

@Scott จุดดี แม้ว่าvi( vimอย่างน้อยก็) ปิดการใช้งาน tty isigเมื่อทำการแก้ไข (มันไม่ได้เกิดขึ้นทันทีเมื่อคุณเรียกใช้:!cmdและนั่นจะเป็นประโยชน์อย่างมากในกรณีนั้น)
Stéphane Chazelas

@ เวลาดูการแก้ไขของฉันเพื่อทำการแก้ไข
Stéphane Chazelas

@ StéphaneChazelasขอบคุณ ดังนั้นจึงเป็นเพราะpingออกด้วย 0 หลังจากได้รับ SIGINT ผมพบว่าพฤติกรรมที่คล้ายกันเมื่อสคริปต์ทุบตีมีsudoแทนpingแต่sudoทางออก 1 หลังจากที่ได้รับ SIGINT unix.stackexchange.com/questions/479023/…
ทิม

13

คำอธิบายก็คือว่าการดำเนินการทุบตี WCE (รอและออกจากสหกรณ์) สำหรับ SIGINT และ SIGQUIT ต่อhttp://www.cons.org/cracauer/sigint.html นั่นหมายความว่าถ้า bash ได้รับ SIGINT หรือ SIGQUIT ในขณะที่รอให้กระบวนการออกมันจะรอจนกว่ากระบวนการจะออกและจะออกจากตัวเองหากกระบวนการออกจากสัญญาณนั้น สิ่งนี้ทำให้มั่นใจได้ว่าโปรแกรมที่ใช้ SIGINT หรือ SIGQUIT ในส่วนต่อประสานผู้ใช้จะทำงานได้ตามที่คาดหวังไว้ (หากสัญญาณไม่ได้ทำให้โปรแกรมหยุดทำงานสคริปต์จะทำงานต่อตามปกติ)

ข้อเสียปรากฏขึ้นพร้อมกับโปรแกรมที่จับ SIGINT หรือ SIGQUIT แต่แล้วก็ยกเลิกเพราะมันใช้การออกปกติ () แทนการส่งสัญญาณไปยังตัวเอง อาจไม่สามารถขัดจังหวะสคริปต์ที่เรียกโปรแกรมดังกล่าวได้ ฉันคิดว่าการแก้ไขที่แท้จริงมีอยู่ในโปรแกรมเช่น ping และ ping6

ksh93 และ FreeBSD's / bin / sh นั้นมีพฤติกรรมที่คล้ายกัน แต่ไม่สามารถใช้งานได้โดยเชลล์ส่วนใหญ่


ขอบคุณที่ทำให้รู้สึกมาก ฉันทราบว่า FreeBSD จะไม่ยกเลิกเช่นกันเมื่อ cmd ออกจากทางออก (130) ซึ่งเป็นวิธีทั่วไปในการรายงานการตายโดย SIGINT ของเด็ก ๆ (mksh ทำexit(130)เช่นนั้นถ้าคุณขัดจังหวะmksh -c 'sleep 10;:')
Stéphane Chazelas

5

ในขณะที่คุณคาดการณ์สิ่งนี้เกิดจาก SIGINT ถูกส่งไปยังกระบวนการรองและเชลล์ดำเนินการต่อหลังจากกระบวนการนั้นจบการทำงาน

เพื่อจัดการสิ่งนี้ในวิธีที่ดีกว่าคุณสามารถตรวจสอบสถานะการออกของคำสั่งที่กำลังทำงานอยู่ โค้ดส่งคืน Unix เข้ารหัสทั้งเมธอดที่ออกจากกระบวนการ (การเรียกระบบหรือสัญญาณ) และค่าใดที่ถูกส่งไปยังexit()หรือสัญญาณใดที่ยกเลิกกระบวนการ ทั้งหมดนี้ค่อนข้างซับซ้อน แต่วิธีที่เร็วที่สุดในการใช้คือรู้ว่ากระบวนการที่ถูกยกเลิกโดยสัญญาณจะมีรหัสส่งคืนที่ไม่เป็นศูนย์ ดังนั้นหากคุณตรวจสอบรหัสส่งคืนในสคริปต์ของคุณคุณสามารถออกจากตัวคุณเองได้หากกระบวนการลูกถูกยุติลงทำให้ไม่จำเป็นต้องใช้ความไม่สะดวกเช่นการsleepโทรที่ไม่จำเป็น วิธีที่รวดเร็วในการทำเช่นนี้ตลอดทั้งสคริปต์ของคุณคือการใช้งานset -eแม้ว่าอาจต้องใช้การปรับแต่งเล็กน้อยสำหรับคำสั่งที่สถานะการออกนั้นเป็นค่าที่ไม่ใช่ศูนย์


1
Set -e ทำงานไม่ถูกต้องใน bash ยกเว้นว่าคุณกำลังใช้ bash-4
schily

"ทำงานไม่ถูกต้อง" หมายถึงอะไร ฉันใช้มันในทุบตี 3 สำเร็จ แต่อาจมีบางกรณีที่ขอบ
Tom Hunt

ในบางกรณีอย่างง่าย bash3 ออกจากข้อผิดพลาด อย่างไรก็ตามสิ่งนี้ไม่ได้เกิดขึ้นในกรณีทั่วไป ตามปกติแล้ว make ไม่หยุดเมื่อสร้างเป้าหมายที่ล้มเหลวและนี่คือจาก makefile ที่ทำงานกับรายการของเป้าหมายในไดเรกทอรีย่อย David Korn และฉันต้องส่งจดหมายไปหลายสัปดาห์กับผู้ดูแลทุบตีเพื่อโน้มน้าวให้เขาแก้ไขข้อผิดพลาดสำหรับ bash4
schily

4
โปรดทราบว่าปัญหาที่นี่คือการpingส่งคืนที่มีสถานะ 0 ออกเมื่อได้รับ SIGINT และbashจากนั้นจะละเว้น SIGINT มันได้รับตัวเองหากเป็นกรณี การเพิ่ม "set -e" หรือตรวจสอบสถานะออกจะไม่ช่วยที่นี่ การเพิ่มแทร็บอย่างชัดเจนบน SIGINT จะช่วยได้
Stéphane Chazelas

4

เทอร์มินัลจะสังเกตเห็น control-c และส่งINTสัญญาณไปยังกลุ่มกระบวนการพื้นหน้าซึ่งในที่นี้จะมีเชลล์เนื่องจากpingไม่ได้สร้างกลุ่มกระบวนการพื้นหน้าใหม่ INTนี้เป็นเรื่องง่ายในการตรวจสอบโดยการวางกับดัก

#! /bin/bash
trap 'echo oh, I am slain; exit' INT
while true; do
  ping -c5 127.0.0.1
done

หากคำสั่งที่กำลังรันได้สร้างกลุ่มกระบวนการพื้นหน้าใหม่ตัวควบคุม -c จะไปที่กลุ่มกระบวนการนั้นไม่ใช่ไปที่เชลล์ ในกรณีนี้เชลล์จะต้องตรวจสอบรหัสทางออกเนื่องจากจะไม่ได้รับสัญญาณจากเทอร์มินัล

( INTการจัดการในเปลือกหอยจะมีความซับซ้อน fabulously โดยวิธีการที่เป็นเปลือกบางครั้งความต้องการที่จะไม่สนใจสัญญาณและบางครั้งไม่มาดำน้ำถ้าอยากรู้อยากเห็นหรือไตร่ตรอง:. tail -f /etc/passwd; echo foo)


ในกรณีนี้ปัญหาไม่ใช่การจัดการสัญญาณ แต่ข้อเท็จจริงที่ว่าทุบตีควบคุมงานในสคริปต์แม้ว่ามันจะไม่ควรดูคำตอบของฉันสำหรับข้อมูลเพิ่มเติม
schily

เพื่อให้ SIGINT ไปที่กลุ่มกระบวนการใหม่คำสั่งจะต้องทำ ioctl () กับเทอร์มินัลเพื่อให้เป็นกลุ่มกระบวนการพื้นหน้าของเทอร์มินัล pingไม่มีเหตุผลที่จะเริ่มกลุ่มกระบวนการใหม่ที่นี่และเวอร์ชั่นของ ping (iputils บน Debian) ซึ่งฉันสามารถสร้างปัญหา OP ขึ้นมาได้ไม่ได้สร้างกลุ่มกระบวนการ
Stéphane Chazelas

1
โปรดทราบว่ามันไม่ใช่เทอร์มินัลที่ส่ง SIGINT มันเป็นระเบียบวินัยของอุปกรณ์ tty (ไดรเวอร์ (รหัสในเคอร์เนล) ของอุปกรณ์ / dev / ttysomething) เมื่อได้รับ unescaped (โดย lnext ปกติ ^ V) ^ C อักขระ จากสถานี
Stéphane Chazelas

2

ฉันพยายามเพิ่ม a sleep 1bash script และ bang! ตอนนี้ฉันสามารถที่จะหยุดมันด้วยสอง
Ctrl+C

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

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

ในสคริปต์ด้วยsleep 1การเรียกนี้จะระงับการดำเนินการเป็นเวลาหนึ่งวินาทีและเมื่อถูกขัดจังหวะด้วยการแรกCtrl+C(แรกSIGINT), subshellจะใช้เวลามากขึ้นในการดำเนินการคำสั่งต่อไป ดังนั้นตอนนี้วินาทีที่Ctrl+CสองSIGINTจะไปที่subshellและการประมวลผลสคริปต์จะสิ้นสุดลง


คุณเข้าใจผิดเกี่ยวกับเชลล์ที่ทำงานได้อย่างถูกต้องมี ^ C เพียงตัวเดียวที่เห็นคำตอบของฉันสำหรับพื้นหลัง
schily

ทีนี้เมื่อพิจารณาว่าคุณได้รับการโหวตแล้วและในขณะนี้คำตอบของคุณมีคะแนน -1 ฉันไม่มั่นใจมากนักฉันควรใช้คำตอบของคุณอย่างจริงจัง
หลานชาย

ความจริงที่ว่าบางคนลงคะแนนไม่เกี่ยวข้องกับคุณภาพของการตอบกลับเสมอไป หากคุณต้องการพิมพ์สองครั้ง ^ c คุณจะตกเป็นเหยื่อของข้อผิดพลาดทุบตีอย่างแน่นอน คุณลองเปลือกที่แตกต่างกันหรือไม่? คุณลองบอร์นเชลล์ตัวจริงหรือไม่?
schily

หากเชลล์ถ้าทำงานอย่างถูกต้องมันจะทำงานทุกอย่างจากสคริปต์ในกลุ่มกระบวนการเดียวกันจากนั้น ^ c เพียงตัวเดียวก็เพียงพอแล้ว
schily

1
พฤติกรรม @nephewtom อธิบายในคำตอบนี้สามารถอธิบายได้ด้วยคำสั่งต่าง ๆ ในสคริปต์ที่ทำงานต่างกันเมื่อพวกเขาได้รับ Ctrl-C หากมีการนอนหลับก็มีโอกาสที่จะได้รับ Ctrl-C ในขณะที่การนอนหลับกำลังดำเนินการ (สมมติว่าทุกอย่างอื่นในลูปนั้นรวดเร็ว) การนอนหลับถูกฆ่าโดยมีค่าการออก 130 ผู้ปกครองของการนอนหลับเชลล์แจ้งให้ทราบว่าการนอนหลับถูกฆ่าโดย sigint และออก แต่ถ้าสคริปต์ไม่มีโหมดสลีป Ctrl-C จะไปที่ ping แทนซึ่งตอบสนองโดยออกด้วย 0 ดังนั้นเชลล์พาเรนต์จะดำเนินการคำสั่งถัดไป
Jonathan Hartley

0

ลองสิ่งนี้:

#!/bin/bash
while true; do
   echo "Ctrl-c works during sleep 5"
   sleep 5
   echo "But not during ping -c 5"
   ping -c 5 127.0.0.1
done

ตอนนี้เปลี่ยนบรรทัดแรกเป็น:

#!/bin/sh

และลองอีกครั้ง - ดูว่าการ ping ขัดจังหวะหรือไม่


0
pgrep -f process_name > any_file_name
sed -i 's/^/kill /' any_file_name
chmod 777 any_file_name
./any_file_name

ตัวอย่างเช่นpgrep -f firefoxจะ grep PID ของการทำงานfirefoxและจะบันทึก PID any_file_nameนี้เพื่อไฟล์ที่เรียกว่า คำสั่ง 'sed' จะเพิ่มหมายเลขkillเริ่มต้นของหมายเลข PID ในไฟล์ 'any_file_name' บรรทัดที่สามจะany_file_nameเรียกใช้ไฟล์ได้ ตอนนี้บรรทัดany_file_nameถัดไปจะฆ่า PID ที่มีอยู่ในไฟล์ เขียนข้างต้นสี่บรรทัดในไฟล์และรันไฟล์ที่สามารถทำ-Control Cทำงานได้ดีอย่างแน่นอนสำหรับฉัน


0

หากใครสนใจแก้ไขbashคุณสมบัตินี้และไม่ได้ยึดติดกับปรัชญามากนักนี่เป็นข้อเสนอ:

อย่าเรียกใช้คำสั่งที่มีปัญหาโดยตรง แต่จากเสื้อคลุมที่) รอให้มันยุติข) ไม่ยุ่งกับสัญญาณและ C) จะไม่ใช้กลไก WCE ตัวเอง SIGINTแต่ก็ตายเมื่อได้รับ

wrapper นั้นสามารถใช้กับawk+ system()function ได้

$ while true; do awk 'BEGIN{system("ping -c5 localhost")}'; done
PING localhost(localhost (::1)) 56 data bytes
64 bytes from localhost (::1): icmp_seq=1 ttl=64 time=0.082 ms
64 bytes from localhost (::1): icmp_seq=2 ttl=64 time=0.087 ms
^C
--- localhost ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1022ms
rtt min/avg/max/mdev = 0.082/0.084/0.087/0.009 ms
[3]-  Terminated              ping -c5 localhost

ใส่ในสคริปต์เช่น OP ของ:

#!/bin/bash
while true; do
        echo -e "\n*** DATE:" `date` " ***";
        echo "********************************************"
        awk 'BEGIN{system(ARGV[1])}' "ping -c5 ${1-localhost}"
done

-3

คุณเป็นเหยื่อของข้อผิดพลาดที่รู้จักกันดี Bash ทำหน้าที่ควบคุมงานของสคริปต์ซึ่งเป็นข้อผิดพลาด

สิ่งที่เกิดขึ้นคือการทุบตีรันโปรแกรมภายนอกในกลุ่มกระบวนการที่แตกต่างจากที่ใช้สำหรับสคริปต์เอง เนื่องจาก TTG processgroup ถูกตั้งค่าเป็น processgroup ของกระบวนการโฟร์กราวน์ปัจจุบันกระบวนการโฟร์กราวน์นี้จะถูกฆ่าและลูปในเชลล์สคริปต์จะดำเนินต่อไป

ในการตรวจสอบ: ดึงและรวบรวมเชลล์เป้าหมายล่าสุดที่ใช้ pgrp (1) เป็นโปรแกรมในตัวจากนั้นเพิ่ม / bin / sleep 100 (หรือ / usr / bin / sleep ขึ้นอยู่กับแพลตฟอร์มของคุณ) ลงในลูปสคริปต์แล้วเริ่ม บอร์นเชลล์ หลังจากที่คุณใช้ ps (1) เพื่อรับ ID กระบวนการสำหรับคำสั่ง sleep และ bash ที่รันสคริปต์ให้เรียกpgrp <pid>และแทนที่ "<pid>" ด้วย ID กระบวนการของ sleep และ bash ที่รันสคริปต์ คุณจะเห็นรหัสกลุ่มกระบวนการที่แตกต่างกัน ตอนนี้เรียกสิ่งที่ชอบpgrp < /dev/pts/7(แทนที่ชื่อ tty ด้วย tty ที่ใช้โดยสคริปต์) เพื่อรับกลุ่มกระบวนการ tty ปัจจุบัน กลุ่มกระบวนการ TTY เท่ากับกลุ่มกระบวนการของคำสั่ง sleep

วิธีแก้ไข: ใช้เชลล์ตัวอื่น

แหล่ง Bourne Shell ล่าสุดอยู่ในชุดเครื่องมือ schily ของฉันซึ่งคุณสามารถหาได้ที่นี่:

http://sourceforge.net/projects/schilytools/files/


รุ่นbashนั้นคืออะไร? AFAIK bashทำเช่นนั้นหากคุณผ่านตัวเลือก -m หรือ -i
Stéphane Chazelas

ดูเหมือนว่าสิ่งนี้จะไม่นำไปใช้กับ bash4 อีกต่อไป แต่เมื่อ OP มีปัญหาดังกล่าวดูเหมือนว่าเขาจะใช้ bash3
schily

ไม่สามารถสร้างใหม่ด้วย bash3.2.48 หรือ bash 3.0.16 หรือ bash-2.05b (ทดลองด้วยbash -c 'ps -j; ps -j; ps -j')
Stéphane Chazelas

/bin/sh -ceนี้แน่นอนที่เกิดขึ้นเมื่อคุณเรียกทุบตีเป็น ฉันต้องเพิ่มวิธีแก้ปัญหาที่น่าเกลียดลงไปในsmakeนั้นเพื่อฆ่ากลุ่มกระบวนการสำหรับคำสั่งที่กำลังทำงานอยู่อย่างชัดเจนเพื่อที่จะอนุญาต^Cให้ยกเลิกการโทรแบบแบ่งชั้น คุณตรวจสอบว่า bash เปลี่ยนกลุ่มกระบวนการจาก id กลุ่มกระบวนการที่เริ่มต้นด้วยหรือไม่
schily

ARGV0=sh bash -ce 'ps -j; ps -j; ps -j'รายงาน pgid เดียวกันสำหรับ ps และ bash ในการเรียกใช้ 3 ps ทั้งหมด (ARGV0 = sh เป็นzshวิธีที่จะผ่าน argv [0])
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.