ฉันจะแยกกระบวนการออกจากสคริปต์ทุบตีได้อย่างไร


18

ฉันกำลังพยายามแยกโพรเซสจาก bash script เพื่อที่ SIGINT จะไม่ถูกส่งต่อไปยังโพรเซสเมื่อฉันออกจากสคริปท์

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

ในเทอร์มินัลมันจะมีหน้าตาดังนี้:

$ openocd &    # run openocd demonized
$ disown $!    # disown last pid
$ gdb          # invoke GDB

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

ความช่วยเหลือใด ๆ ที่จะได้รับการชื่นชมอย่างมาก.

ป.ล. ปัญหานี้อยู่ใน OS X แต่ฉันพยายามใช้เครื่องมือที่พกพาไปยังเครื่องมือ Unix ทั้งหมด


nohupไม่ใช่คำตอบที่ถูกต้องทีเดียว คุณควรเพิ่มรหัสเทียมหรือโค้ดตัวอย่างเพื่อแสดงสิ่งที่คุณต้องการอย่างแม่นยำยิ่งขึ้น
Bruce Ediger

1
คุณเปิดให้ใช้เครื่องมือเช่นนี้screenหรือไม่?
Eric Renouf

คำตอบ:


16

ในการแยกโพรเซสออกจาก bash script:

nohup ./process &

หากคุณหยุดสคริปต์ทุบตีด้วยSIGINT(ctrl + c) หรือเชลล์ออกจากการส่งSIGHUPตัวอย่างกระบวนการจะไม่รบกวนและจะดำเนินการตามปกติ stdoutและจะถูกนำไปล็อกไฟล์:stderrnohup.out

หากคุณต้องการรันคำสั่งเดี่ยวขณะที่สามารถเห็นเอาต์พุตในเทอร์มินัลให้ใช้tail:

TEMP_LOG_FILE=tmp.log
> "$TEMP_LOG_FILE"
nohup ./process &> "$TEMP_LOG_FILE" & tail -f "$TEMP_LOG_FILE" &

ทำไมเป็นnohupnecassary? อะไรคือความแตกต่างระหว่างnohup COMMAND &และCOMMAND &ถ้าเป้าหมายของคุณคือการรันคำสั่งในพื้นหลังและปล่อยเทอร์มินัลเท่านั้น
James Wierzba

@JamesWierzba หนึ่งในความแตกต่างคือถ้าคุณต้องการคำสั่งให้ทำงานต่อไปแม้หลังจากออกจากเชลล์แล้ว nohup ก็เป็นหนทางที่จะไป มีคำอธิบายมากมายในเว็บ เช่นstackoverflow.com/questions/15595374/…
marc


4

วิธีแก้ปัญหาที่ฉันพบเกี่ยวข้องกับโปรแกรมที่เรียกว่า 'detach' เขียนโดย Annon Inglorion และสามารถดาวน์โหลดได้จากเว็บไซต์ของเขา

เมื่อรวบรวมแล้วจะสามารถใช้ในสคริปต์ดังต่อไปนี้:

$ ./detach -p debug.pid openocd <args> # detach openocd
$ gdb <args>                           # run gdb
$ kill -9 $(cat debug.pid)             # end openocd process
$ rm debug.pid                         # remove file containing process id

บรรทัดแรกนี้สร้างกระบวนการใหม่ (เรียกใช้ openocd) และเก็บ id กระบวนการไว้ในไฟล์ (debug.pid) เพื่อใช้ในภายหลัง วิธีนี้ช่วยป้องกันปัญหาเกี่ยวกับการ greid สำหรับ pid ตามที่ระบุไว้ในคำตอบของ Oliver เมื่อออกจากโปรแกรมการบล็อกถัดไป (gdb) ไฟล์ที่จัดเก็บ pid จะถูกใช้เพื่อฆ่ากระบวนการที่แยกออกโดยตรง


สามารถยืนยันdetachทำให้สิ่งมหัศจรรย์
AS

2

โซลูชันที่ง่ายและพกพาได้:

echo "openocd" | at now #openocd starts now, but via the at daemon, not the current shell!
pid=$(ps -ef | grep "[o]penocd" | awk '{print $1}')  
echo "openocd is running with pid: $pid"
gdb

คำเตือนการพกพาบางpsตัว: ตัวเลือกขึ้นอยู่กับระบบปฏิบัติการ! { ps -ef || ps aux ;} | grep '[o]penocd | cut -f 1คุณสามารถใช้แทนตัวแปรของ: atไม่สามารถใช้งานได้ (แปลก แต่สิ่งนี้เกิดขึ้น ... ) $(...)ต้องการเชลล์เก่าที่ไม่ได้ reallllly มิฉะนั้นใช้ backticks


ดูเหมือนว่าจะเป็นอันตรายการ grepping สำหรับ pid อาจทำสิ่งที่ไม่คาดคิดหากมีมากกว่าหนึ่งโพรเซสกำลังทำงานด้วยชื่อเดียวกันหรือแม้กระทั่งถ้าโพรเซสอื่นมีคำว่า openocd
orion

1
@orion: ฉันให้ตัวอย่างง่ายๆเพื่อให้ความคิดเกี่ยวกับสิ่งที่คุณพูดถึงนั้นง่ายต่อการกำจัด: atเริ่มต้นสคริปต์ที่เปิดตัวโปรแกรมและแจก pid แทนในไฟล์และให้สคริปต์หลักรอสิ่งนั้นอยู่ ไฟล์ที่จะปรากฏแล้วอ่าน pid จากมัน
Olivier Dulac

แน่นอนคุณควรแทนที่ในตัวอย่างของฉัน (ง่ายเกินไป) grep ด้วยการทดสอบภายใน awk บนคอลัมน์ขวา ($ 8 ปกติ) (คอลัมน์ขึ้นอยู่กับระบบปฏิบัติการของคุณและรุ่น / ตัวเลือกของ ps)
Olivier Dulac
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.