ความแตกต่างระหว่าง nohup, บอกเลิกและ &


579

อะไรคือความแตกต่างระหว่าง

$ nohup foo

และ

$ foo &

และ

$ foo & 
$ disown

50
รอคุณสามารถบอกเลิกโดยไม่ระบุ PID ได้หรือไม่ ที่ดี!
ripper234

34
นอกจากนี้ยังมีfoo &!ซึ่งควรจะเท่ากับการปฏิเสธมันตั้งแต่เริ่มต้น
user4514

26
Bash ไม่รองรับ &!
Jonas Kongslund

20
foo & disownจะบอกเลิกทันที
ctrl-alt-delor

9
ฉันชอบที่จะเห็นการกล่าวถึงsetsidและมันเกี่ยวข้องกับdisownและnohup
YoungFrog

คำตอบ:


558

ก่อนอื่นเรามาดูกันว่าจะเกิดอะไรขึ้นถ้าโปรแกรมเริ่มต้นจากเชลล์แบบโต้ตอบ (เชื่อมต่อกับเทอร์มินัล) โดยไม่มี&(และไม่มีการเปลี่ยนทิศทาง) ดังนั้นสมมติว่าคุณเพิ่งพิมพ์foo:

  • กระบวนการทำงานfooถูกสร้างขึ้น
  • กระบวนการสืบทอด stdin, stdout และ stderr จากเชลล์ ดังนั้นจึงเชื่อมต่อกับเทอร์มินัลเดียวกัน
  • หากเชลล์ได้รับ a SIGHUPมันจะส่ง a SIGHUPไปยังกระบวนการ (ซึ่งโดยปกติจะทำให้กระบวนการยุติ)
  • มิฉะนั้นเชลล์จะรอ (ถูกบล็อก) จนกว่ากระบวนการจะสิ้นสุดลง

ทีนี้มาดูกันว่าจะเกิดอะไรขึ้นถ้าคุณใส่โพรเซสในแบ็คกราวน์นั่นคือพิมพ์foo &:

  • กระบวนการทำงานfooถูกสร้างขึ้น
  • กระบวนการสืบทอด stdout / stderr จากเชลล์ (ดังนั้นจึงยังคงเขียนไปยังเทอร์มินัล)
  • กระบวนการในหลักการยังสืบทอด stdin แต่ทันทีที่พยายามอ่านจาก stdin จะหยุดทำงาน
  • มันถูกใส่ลงในรายการงานพื้นหลังที่เชลล์จัดการซึ่งหมายถึงโดยเฉพาะ:
    • มันถูกแสดงรายการด้วยjobsและสามารถเข้าถึงได้โดยใช้%n(ซึ่งnเป็นหมายเลขงาน)
    • สามารถเปลี่ยนเป็นงานพื้นหน้าโดยใช้fgซึ่งในกรณีนี้จะดำเนินต่อไปราวกับว่าคุณไม่ได้ใช้งาน&(และหากหยุดทำงานเนื่องจากพยายามอ่านจากอินพุตมาตรฐานตอนนี้สามารถดำเนินการอ่านจากเทอร์มินัลได้)
    • หากเชลล์ได้รับ a SIGHUPก็จะส่ง a SIGHUPไปยังกระบวนการ ขึ้นอยู่กับเชลล์และตัวเลือกที่ตั้งค่าไว้สำหรับเชลล์เมื่อยกเลิกเชลล์มันจะส่งSIGHUPกระบวนการไปให้

ตอนนี้disownลบงานออกจากรายการงานของเชลล์ดังนั้นจุดย่อยทั้งหมดข้างต้นจึงไม่นำไปใช้เพิ่มเติม (รวมถึงกระบวนการที่ส่งSIGHUPโดยเชลล์) อย่างไรก็ตามโปรดทราบว่ามันยังคงเชื่อมต่อกับเทอร์มินัลดังนั้นหากเทอร์มินัลถูกทำลาย (ซึ่งสามารถเกิดขึ้นได้หากเป็น pty เช่นที่สร้างโดยxtermหรือหรือsshและโปรแกรมควบคุมถูกยกเลิกโดยปิด xterm หรือยกเลิกการเชื่อมต่อSSH ) โปรแกรมจะล้มเหลวทันทีที่พยายามอ่านจากอินพุตมาตรฐานหรือเขียนไปยังเอาต์พุตมาตรฐาน

สิ่งที่nohupไม่อยู่ในมืออื่น ๆ ที่เป็นไปได้อย่างมีประสิทธิภาพแยกกระบวนการจากท่าเรือ:

  • มันปิดอินพุตมาตรฐาน (โปรแกรมจะไม่สามารถอ่านอินพุตใด ๆ ได้แม้ว่าจะถูกรันในเบื้องหน้ามันไม่ได้หยุดทำงาน แต่จะได้รับรหัสข้อผิดพลาดหรือEOF)
  • มันเปลี่ยนเส้นทางเอาต์พุตมาตรฐานและข้อผิดพลาดมาตรฐานไปยังไฟล์nohup.outดังนั้นโปรแกรมจะไม่ล้มเหลวในการเขียนไปยังเอาต์พุตมาตรฐานหากเทอร์มินัลล้มเหลวดังนั้นสิ่งที่กระบวนการเขียนจะไม่สูญหาย
  • มันป้องกันกระบวนการจากการรับSIGHUP(เช่นชื่อ)

โปรดทราบว่าnohupไม่ไม่เอากระบวนการตั้งแต่การควบคุมงานของเปลือกและยังไม่ได้ใส่ไว้ในพื้นหลัง ( แต่ตั้งแต่เบื้องหน้าnohupงานจะมากหรือน้อยไร้ประโยชน์โดยทั่วไปคุณต้องการใส่มันลงไปในพื้นหลังโดยใช้&) ตัวอย่างเช่นไม่เหมือนกับdisownเชลล์เชลล์จะยังคงบอกคุณเมื่องาน nohup เสร็จสมบูรณ์ (ยกเว้นกรณีที่เชลล์ถูกยกเลิกก่อนแน่นอน)

ดังนั้นเพื่อสรุป:

  • & วางงานไว้ในพื้นหลังนั่นคือทำให้มันบล็อคในการพยายามอ่านอินพุตและทำให้เชลล์ไม่รอให้เสร็จสมบูรณ์
  • disownลบกระบวนการออกจากการควบคุมงานของเชลล์ แต่ยังคงปล่อยให้เชื่อมต่อกับเทอร์มินัล SIGHUPหนึ่งในผลที่ได้คือว่าเชลล์จะไม่ส่งมัน เห็นได้ชัดว่ามันสามารถใช้ได้กับงานแบ็คกราวน์เท่านั้นเนื่องจากคุณไม่สามารถป้อนได้เมื่อมีการทำงานเบื้องหน้า
  • nohupยกเลิกการเชื่อมต่อกระบวนการจาก terminal, เปลี่ยนเส้นทางการส่งออกไปยังและโล่จากnohup.out SIGHUPหนึ่งในผลกระทบ (ตั้งชื่อหนึ่ง) คือกระบวนการที่จะไม่ได้รับการใด ๆ SIGHUPที่ส่ง มันเป็นอิสระอย่างสมบูรณ์จากการควบคุมงานและในหลักการสามารถใช้สำหรับงานเบื้องหน้าได้ด้วย (แม้ว่ามันจะไม่ได้มีประโยชน์มาก)

8
+1 ขอบคุณ จะเกิดอะไรขึ้นเมื่อใช้การปฏิเสธไม่ปล่อยและ & ร่วมกัน?
ทิม

15
หากคุณใช้ทั้งสามอย่างพร้อมกันกระบวนการกำลังทำงานในพื้นหลังจะถูกลบออกจากการควบคุมงานของเชลล์และตัดการเชื่อมต่อจากเทอร์มินัลอย่างมีประสิทธิภาพ
celtschk


1
ความแตกต่างระหว่างdisown %1และdisown -h %1คืออะไร คนที่สองจะยังคงเป็นงานประจำ (แต่ไม่สนใจสัญญาณ HUP) จนกว่าขั้วจะออก?
schemacs

4
อาจคุ้มค่าที่จะรวมถึง(foo&)subshell
jiggunjer

169

การใช้&ทำให้โปรแกรมทำงานในพื้นหลังดังนั้นคุณจะได้รับพรอมต์เชลล์ใหม่แทนที่จะปิดกั้นจนกว่าโปรแกรมจะจบ nohupและdisownไม่เกี่ยวข้องส่วนใหญ่; พวกเขาระงับสัญญาณ SIGHUP (hangup) ดังนั้นโปรแกรมจะไม่ถูกฆ่าโดยอัตโนมัติเมื่อปิดเทอร์มินัลการควบคุม nohupทำสิ่งนี้เมื่อเริ่มงานเป็นครั้งแรก หากคุณไม่ได้nohupงานเมื่อเริ่มต้นคุณสามารถใช้disownเพื่อแก้ไขงานที่กำลังทำงานอยู่ โดยไม่มีข้อโต้แย้งมันแก้ไขงานปัจจุบันซึ่งเป็นงานที่เพิ่งมีพื้นหลัง


10
ความแตกต่างเล็กน้อยระหว่าง nohup และ disown: คำสั่ง disown จะลบออกจากรายการงานของคุณ nohup จะไม่
Shawn J. Goff

191
nohupและdisownทั้งคู่สามารถพูดเพื่อปราบปรามSIGHUPแต่ในวิธีที่ต่างกัน nohupทำให้โปรแกรมไม่สนใจสัญญาณในตอนแรก (โปรแกรมอาจเปลี่ยนแปลงสิ่งนี้) nohupพยายามจัดเรียงโปรแกรมไม่ให้มีเทอร์มินัลการควบคุมเพื่อที่SIGHUPเคอร์เนลจะไม่ถูกส่งเมื่อปิดเทอร์มินัล disownอยู่ภายในอย่างหมดจดเพื่อเปลือก; มันทำให้เชลล์ไม่ส่งSIGHUPเมื่อมันยกเลิก
Gilles

27
@Gilles ความคิดเห็นของคุณคุ้มค่ากับคำตอบของตัวเอง
lesmana

5
เพียงแค่ชี้แจงเกี่ยวกับความคิดเห็นของ @ ShawnJ.Goff เกี่ยวกับการdisownลบงานออกจากรายการงาน หากคุณไม่ได้ระบุตัวเลือกมันจะลบออกจากรายการงาน อย่างไรก็ตามหากคุณระบุ-hตัวเลือกแต่ละงานจะไม่ถูกลบออกจากตาราง แต่ก็จะทำให้มันเพื่อที่จะไม่ถูกส่งไปทำงานถ้าเปลือกได้รับSIGHUP SIGHUP
tacotuesday

4
เพียงเพื่อชี้แจงการใช้&ไม่ได้ให้เทอร์มินัลคุณจะแยกออกstdinจากกระบวนการและทำให้มันทำงานในพื้นหลัง แต่ทั้งสองอย่างstdoutและstderrยังคงแนบกับ tty ปัจจุบัน ซึ่งหมายความว่าคุณอาจได้รับข้อความจากโปรแกรมต่าง ๆ มารวมกันซึ่งอาจน่ารำคาญถ้าคุณทำgimp &และรับข้อผิดพลาด GTK + จำนวนมากในขณะที่พยายามใช้ tty นั้นเพื่อสิ่งอื่น
แฟรงค์

8

นี่คือประสบการณ์ของฉันพยายามเรียกใช้ soffice ในพื้นหลังตามคำสั่งไม่สิ้นสุด (เช่นtail) sleep 100สำหรับตัวอย่างนี้ผมจะใช้

&

#!/bin/bash
/opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

ผมเห็น soffice บันทึก / โดยการกดCtrl- Cหยุด soffice

ไม่นะ .. &

#!/bin/bash
nohup /opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

ฉันไม่เห็น soffice บันทึก / โดยการกดCtrl- Cหยุด soffice

& ปฏิเสธ

#!/bin/bash
/opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard & disown
sleep 100

ผมเห็น soffice บันทึก / โดยการกดCtrl- Cหยุด soffice

setsid .. &

#!/bin/bash
setsid /opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

ฉันเห็นไฟล์บันทึก soffice / โดยกดCtrl- CSoffice ไม่ได้หยุด

เพื่อประหยัดพื้นที่:
nohup setsid ..: ไม่แสดง logs / soffice ไม่หยุดบนCtrl-C
nohupมี& disownที่สิ้นสุด: ไม่แสดง logs / soffice หยุดบนCtrl-C


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

1
@YoungFrog ฉันจะเห็นด้วยกับเรื่องนี้!
Marinos An

สำหรับผมกับกระบวนการสร้างขึ้นไม่หยุดnohup ⟨command⟩ & disown Ctrl+C
k.stm

@ k.stm คุณลองsofficeหรือยัง sofficeคำสั่งดูเหมือนจะมีสิ่งที่แตกต่าง ดังนั้นฉันจึงพิจารณาเพิ่มที่นี่เป็นข้อยกเว้นกฎ เช่นเมื่อใช้: nohup .. &กดCtrl-cตามปกติไม่ก่อให้เกิดคำสั่งที่จะหยุด แต่ด้วยความsofficeที่มันไม่ ฉันรอจนกว่าจะมีใครสักคนเหยียบย่ำเรื่องนี้และอธิบายว่าทำไมสิ่งนี้จึงเกิดขึ้นกับ soffice :)
23499 Marinos

@MarinosAn ใช่ฉันทำ ฉันวิ่งและกดnohup soffice & Ctrl+Cไม่มีอะไรเกิดขึ้นตามที่คาดไว้
k.stm
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.