ฉันใช้ `&`: ทำไมกระบวนการไม่ทำงานในพื้นหลัง


24

ฉันรู้ว่าฉันสามารถต่อท้าย&คำสั่งเพื่อเรียกใช้กระบวนการในพื้นหลัง

ฉันกำลังเข้า SSH ในกล่อง Ubuntu 12.04 และรันโปรแกรมไพ ธ อนด้วย$python program.py &- แต่เมื่อฉันไปปิดหน้าต่างเทอร์มินัลฉันได้รับข้อความแจ้งว่าการปิดเทอร์มินัลจะเป็นการฆ่ากระบวนการที่กำลังทำงานอยู่

ทำไมนี้ ฉันใช้เครื่องหมายและการเรียกใช้กระบวนการในพื้นหลัง ฉันจะให้มันทำงานได้อย่างไรโดยไม่คำนึงว่าฉันเป็น SSH หรือไม่


ข้อมูลซ้ำของunix.stackexchange.com/q/4004/69080
Joshua Huber

apt-get install screen, man screen
captcha

คำตอบ:


51

เมื่อคุณปิดหน้าต่างเทอร์มินัลเครื่องจำลองเทอร์มินัลส่ง SIGHUP ไปยังกระบวนการที่กำลังทำงานเชลล์ของคุณ กระสุนของคุณส่งต่อไปที่ SIGHUP กับทุกสิ่งที่มันทำงานอยู่ บนระบบโลคัลของคุณนี่คือ ssh ssh จะส่งต่อ SIGHUP ไปยังสิ่งที่มันกำลังทำงานเชลล์ระยะไกล ดังนั้นรีโมตเชลล์ของคุณจึงส่ง SIGHUP ไปยังโปรเซสทั้งหมดของมัน, โปรแกรมที่แบ็กกราวน์ของคุณ

มี 2 ​​วิธีรอบนี้

  1. ยกเลิกการเชื่อมโยงโปรแกรมพื้นหลังจากเชลล์ของคุณ
    1. ใช้disownคำสั่งหลังจากพื้นหลังกระบวนการของคุณ สิ่งนี้จะทำให้เปลือกลืมเกี่ยวกับมัน
    2. คำนำหน้าคำสั่งของคุณด้วยnohup( nohup $python program.py &) สิ่งนี้ทำสิ่งเดียวกันได้สำเร็จ แต่โดยใช้กระบวนการระดับกลาง โดยทั่วไปจะไม่สนใจสัญญาณ SIGHUP จากนั้นให้ & & รันโปรแกรมของคุณซึ่งสืบทอดการตั้งค่าจากนั้นออก เนื่องจากมันเป็นทางแยกโปรแกรมที่เปิดตัวไม่ใช่ลูกของเชลล์และเชลล์ไม่รู้เกี่ยวกับมัน และหากไม่ได้ติดตั้งตัวจัดการสัญญาณสำหรับ SIGHUP มันจะไม่ดำเนินการใด ๆ
  2. ใช้logoutแทนการปิดหน้าต่างเทอร์มินัล เมื่อคุณใช้งานlogoutนี่ไม่ใช่ SIGHUP และดังนั้นเชลล์จะไม่ส่ง SIGHUP ให้กับลูก ๆ ของมัน

นอกจากนี้คุณต้องตรวจสอบให้แน่ใจว่าโปรแกรมของคุณไม่ได้เขียนไปยังเทอร์มินัลผ่าน STDOUT หรือ STDERR เนื่องจากทั้งสองโปรแกรมจะไม่มีอยู่อีกต่อไปเมื่อเทอร์มินัลออก หากคุณไม่เปลี่ยนเส้นทางไปยังบางสิ่งเช่น/dev/nullโปรแกรมจะยังคงทำงาน แต่หากพยายามเขียนถึงมันโปรแกรมจะรับ SIGPIPE และการกระทำเริ่มต้นของ SIGPIPE คือการฆ่ากระบวนการ)


4
ในทางเทคนิคการsshตายเป็นสาเหตุให้การเชื่อมต่อลดลงการเชื่อมต่อจะทำให้เกิดการลดลงsshdในส่วนอื่น ๆ ที่จะตาย sshd นั้นควบคุมด้านต้นแบบของเทอร์มินัลหลอกที่รีโมตเชลล์รันเมื่อมันตายนั่นคือการวางสาย (มันเหมือนกับการดึงปลั๊กบนเทอร์มินัลจริง) ดังนั้นระบบจึงส่ง SIGHUP ไปยังรีโมตเชลล์
Stéphane Chazelas

@ StéphaneChazelasนั่นเป็นสิ่งหนึ่งที่ฉันไม่เคยขุดลงไป หากเคอร์เนลทำเช่นนั้นจะกำหนดกระบวนการที่จะทำการ SIGHUP ได้อย่างไร เห็นได้ชัดว่าไม่ได้รวบรวมทุกสิ่งด้วยตัวอธิบายไฟล์ที่เปิดให้ TTY นั้นเนื่องจากโปรแกรมจะยังคงทำงานต่อไปตราบใดที่ไม่พยายามใช้ ดังนั้นจะเลือกโปรแกรมที่กำลังอ่านจาก STDIN (เนื่องจากมีเพียงหนึ่งโปรแกรมเท่านั้นที่สามารถอ่านได้จาก STDIN ในแต่ละครั้ง)
Patrick

4
ไม่เป็นไรตอบคำถามของฉันเอง POSIX IEEE 1003.1 เด็กชาย 11 หากมีการตัดการเชื่อมต่อโมเด็มถูกตรวจพบโดยอินเตอร์เฟซสำหรับสถานีควบคุมขั้ว ... สัญญาณ SIGHUP จะถูกส่งไปยังกระบวนการควบคุม
Patrick

2
นอกจากนี้โปรดทราบว่าnohupสร้างnohup.outไฟล์ที่มีเอาต์พุตของโปรแกรมที่คุณเริ่มด้วย อาจเป็นเรื่องที่น่ารำคาญที่จะลบไฟล์นั้นทุกครั้งที่คุณใช้ nohup เพื่อเริ่มแอพด้วยวิธีนี้ (หรือคุณต้องเปลี่ยนเส้นทางไฟล์ที่ส่งไปยัง/dev/null)
Ruslan

1
แทนที่จะnohup python program.py &แนะนำให้ใช้setsid python program.pyแทนซึ่งจะปฏิเสธโปรแกรมทันที
Hitechcomputergeek

14

กระบวนการทำงานในพื้นหลังในเทอร์มินัล แต่เอาต์พุตจากstdout(และstderr) ยังคงถูกส่งไปยังเทอร์มินัล หากต้องการหยุดสิ่งนี้ให้เพิ่ม> /dev/null 2>&1ก่อนที่&จะเปลี่ยนเส้นทางทั้งผลลัพธ์ไปยัง/dev/null- การเพิ่มdisownให้แน่ใจว่ากระบวนการไม่ได้ถูกฆ่าหลังจากคุณปิดเทอร์มินัล:

COMMAND > /dev/null 2>&1 & disown

ในกรณีของคุณสิ่งนี้จะเป็น:

python program.py > /dev/null 2>&1 & disown

3

&ผู้ประกอบการแยกคำสั่งให้ทำงานในแบบคู่ขนานเช่นเดียวกับ;คำสั่งแยกที่จะทำงานในซีรีส์ ทั้งสองชนิดของคำสั่งที่จะยังคงทำงานเป็นเด็กของกระบวนการเปลือก

ดังนั้นเมื่อคุณปิดเปลือกซึ่งเริ่มเด็กเหล่านั้นเด็ก ๆ จะถูกปิดด้วย

สิ่งที่คุณต้องการคือกระบวนการ daemonซึ่งมีความยุ่งยากมากขึ้นเพราะต้องแยกจากกระบวนการหลักทั้งหมด เปลือกมักจะไม่มีวิธีง่ายๆในการทำเช่นนั้น


1

เมื่อคุณออกจากระบบกระบวนการพื้นหลังที่เกี่ยวข้องกับเซสชั่นการเข้าสู่ระบบจะถูกฆ่าตามปกติ nohupหากคุณต้องการให้พวกเขาได้รับการตัดการเชื่อมต่อจากการเรียกใช้พวกเขาด้วย

nohup python program.py &

1

หลังจากคำสั่งลงท้ายด้วย ampersand ( &) ที่พรอมต์คำสั่งให้รันคำสั่งbg:

bash> python program.py &  
bash> bg  

สิ่งนี้จะทำให้คำสั่ง "&" เป็นพื้นหลัง

bash> jobs  

นี่จะแสดงรายการงานที่กำลังทำอยู่ในพื้นหลัง

bash> fg 1   

นี่จะนำ Job # 1 มาที่เบื้องหน้า

อีกวิธีหนึ่ง (เพื่อให้สามารถออกจากระบบ)

bash> at now  
bash> /full/path/python /full/path/program.py  
bash> ^d   `(# That is, Control-D, to run the command, Control-C to cancel)`  

หลายบรรทัดสามารถส่งไปยังatคำสั่งก่อน ^ d (Control-D) ดู
man at

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