เหตุใดจึงรันคำสั่ง Linux shell ด้วย '&'


30

ฉันใช้ Red Hat Linux Enterprise เวอร์ชัน 5 ฉันสังเกตว่าบางครั้งผู้คนกำลังใช้คำสั่งพร้อม&ตัวเลือกสองสามตัว ตัวอย่างเช่นในคำสั่งด้านล่างมีสอง&สัญญาณ พวกเขามีจุดประสงค์อะไร? พวกเขามักจะใช้ร่วมกับ nohup หรือไม่?

nohup foo.sh <script parameters> >& <log_file_name> &

คำตอบ:


15

นอกจากของ Martin คำตอบของ Ash's และ Kevin บางครั้งคุณจะเห็นเครื่องหมายและใช้คณิตศาสตร์ในระดับบิตและ* :

$ echo $(( 11 & 7 ))
3

ในกรณีที่คุณไม่คุ้นเคยกับตัวดำเนินการบิต:

11: 1011
 7: 0111
-------- AND
 3: 0011

ในแต่ละตำแหน่งจะมีบิตหนึ่งในหมายเลขแรกและหมายเลขที่สองให้ตั้งค่าบิตนั้นเป็นหนึ่งในคำตอบ

* คุณสมบัติในคำตอบของ Kevin ถูกอ้างถึงว่าเป็นตรรกะและ

เพื่ออธิบายรายละเอียดของคำตอบของ Ash เมื่อใช้ในการเปลี่ยนทิศทางเครื่องหมายและสามารถบอกเชลล์ให้คัดลอกไฟล์ descriptor ในคำสั่งนี้echo "hello" > outputfile 2>&1เครื่องหมายแอมเปอร์แซนด์ทำให้เกิดเอาต์พุตใด ๆ ที่อาจเกิดข้อผิดพลาดมาตรฐาน (stderr, file descriptor 2) เพื่อไปยังตำแหน่งเดียวกับเอาต์พุตมาตรฐาน (stdout, file descriptor 1, ค่าดีฟอลต์สำหรับด้านซ้ายของ>) ผู้ประกอบการมีการจดชวเลข>& outputfile> outputfile 2>&1

นอกจากนี้ใหม่ใน Bash 4 มีสองเทอร์มิเนเตอร์ใหม่สำหรับส่วนcaseคำสั่งในคำสั่ง;&และ;;&ส่งผลต่อกรณีที่ "ตกหล่น" และถ้าเป็นเช่นนั้นจะทำการทดสอบครั้งต่อไปหรือไม่


เจ๋งเดนนิส! สมมติว่าฉันใช้บันทึกเทอร์มินัล ssh ในเครื่องจากนั้นใช้เทอร์มินัล ssh เพื่อดำเนินการคำสั่ง (สมมติว่าเป็นกระบวนการระยะยาว) ถ้าฉันออกจากเซสชันเทอร์มินัลกระบวนการระยะยาวของคำสั่งจะถูกต้อง และถ้าฉันต้องการให้คำสั่งดำเนินการต่อไปแม้ว่าฉันจะออกจาก shell ฉันควรใช้ nohup หรือ & (ที่ส่วนท้ายของคำสั่ง) หรือใช้ทั้ง nohup และ &?
George2

1
@ George2: ไม่>& filenameเอาต์พุตทั้ง stdout และ stderr ไปที่ไฟล์เดียวกัน หากคุณต้องการเปลี่ยนเส้นทาง stderr เท่านั้น (และปล่อยให้อยู่คนเดียว stdout) 2> filenameที่คุณต้องการจะทำอย่างไร สำหรับคำถามอื่น ๆ ของคุณส่วนใหญ่มีแนวโน้มที่คุณจะใช้ทั้งสองและnohup &
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

1
@ George2: ถ้าคุณไม่ทำแบ็คกราวน์ของคำสั่งคุณจะไม่ได้รับคำสั่งจากเชลล์เพื่อให้คุณสามารถออกคำสั่งlogoutหรือ exit
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

2
จอร์จ: ถ้าคุณไม่ใช้ & คุณจะไม่ได้รับคำตอบกลับให้ทำอะไรอีกเลย เทอร์มินัลจะ“ หยุดทำงาน” จนกว่ากระบวนการ (ไม่ว่าจะเกิดอะไรขึ้น) เสร็จสิ้นหรือถูกยกเลิก / ฆ่า & รับประกันว่ากระบวนการทำงานในพื้นหลัง อย่างไรก็ตามหากคุณออกจากระบบปฏิบัติการจะยุติกระบวนการทั้งหมดของคุณซึ่งฆ่ากระบวนการพื้นหลังของคุณเช่นกัน ถ้าคุณใช้nohup คุณกำลังบอกกระบวนการ“ เพิกเฉยคำสั่งที่จะยุติคุณ”
Martin Marconcini

1
@ George2: ใช่ "ภูมิคุ้มกันต่อ hangups" == "ดำเนินการต่อ" และ "ไม่ใช่ tty" == "ออกจากเซสชันคอนโซลเทอร์มินัล"
หยุดชั่วคราวจนกว่าจะมีประกาศ

32

ใน Bash shell script, เครื่องหมาย &“ &” ใช้เพื่อแยกกระบวนการ:

find -name hello &

มันจะทำให้คำสั่ง find ถูกแยกและทำงานในพื้นหลัง (คุณสามารถฆ่ามันด้วย PID)


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

1
นั่นคือจอร์จที่ถูกต้อง กระบวนการพื้นหลังควรดำเนินการต่อไปจนกว่าพวกเขาจะออกหรือคุณฆ่าพวกเขา อย่างไรก็ตามตามที่ได้มีการชี้ให้เห็นแล้วคุณจะไม่ต้องรอเพื่อให้กระบวนการตายเมื่อผู้ใช้ออกจากระบบ
Martin Marconcini

ขอบคุณมาร์ติน! ฉันต้องการทราบว่าทำไมเราต้องใช้ทั้ง & และ nohup และฟังก์ชั่นส่วนบุคคลของพวกเขาที่ทำให้เราบรรลุเป้าหมายในการปล่อยให้คำสั่งทำงานต่อไปแม้ว่าคอนโซลเทอร์มินัลจะหยุดทำงาน ฉันอ่าน man page สำหรับ nohup และมีการกล่าวถึง "เรียกใช้คำสั่งภูมิคุ้มกันต่อ hangups ด้วยผลลัพธ์ที่ไม่ใช่ tty" ฉันสับสนว่าภูมิคุ้มกันต่อ hangups เป็นสิ่งที่คุณหมายถึงการให้คำสั่งยังคงทำงานโดยไม่ได้รับผลกระทบจากการเลิก เทอร์มินัลคอนโซล ถ้าเป็นเช่นนั้นฉันคิดว่าการใช้ nohup ก็เพียงพอแล้วและไม่จำเป็นต้องใช้ & มีคำแนะนำอะไรมั้ย?
George2

1
คุณต้องใช้ทั้งสองอย่างหากไม่ได้ใช้ & เทอร์มินัลจะไม่อนุญาตให้คุณป้อนคำสั่งอื่น ๆ วิธีที่ดีที่สุดสำหรับคุณที่จะเห็นมันก็แค่ลองดู ตัวอย่างที่ดีคือคำสั่งที่ใช้เวลาพอสมควรเช่น find: find-find SomeName /> somefile.txt ลองใช้ nohup และ & และดูความแตกต่าง
Martin Marconcini

นี่มีคำตอบที่ดีสำหรับคำถาม nohup: serverfault.com/questions/311593/…
joshperry

26

เหตุใดจึงรันคำสั่ง Linux shell ด้วย '&'

ในการรับพรอมต์ของคุณกลับมาทันทีและเรียกใช้กระบวนการในพื้นหลัง

หน้าที่ของพวกเขาคืออะไร?

nohupอนุญาตให้กระบวนการพื้นหลังทำงานต่อไปแม้หลังจากที่ผู้ใช้ล็อกเอาต์ (หรือออกจากเชลล์เริ่มต้น)

> & เปลี่ยนเส้นทางทั้งเอาต์พุตมาตรฐานและข้อผิดพลาดมาตรฐานไปยังไฟล์บันทึก

&รันทุกสิ่งในพื้นหลังโดยให้คุณตอบกลับทันที

คำอธิบาย:

ทุกกระบวนการ Linux เปิดช่อง I / O สามช่องสัญญาณ "stdin", เอาต์พุตมาตรฐาน "stdout" และเอาต์พุตข้อผิดพลาดมาตรฐาน "stderr" พวกเขาสามารถใช้สำหรับไบนารี แต่พวกเขาเป็นข้อความแบบดั้งเดิม เมื่อโปรแกรมส่วนใหญ่เห็น stdin close พวกเขาจะออก (ซึ่งสามารถเปลี่ยนแปลงได้โดยโปรแกรมเมอร์)

เมื่อเชลล์พาเรนต์ออก stdin จะปิดลงบนลูกและ (โดยปกติมัก) ลูกก็จะออกจากเช่นกัน นอกจากนี้เด็ก ๆ ยังได้รับสัญญาณซอฟต์แวร์ SIGHUP ซึ่งระบุว่าผู้ใช้มี "วางสาย" (เดิมคือโมเด็ม) และค่าเริ่มต้นที่นี่ก็คือออกเช่นกัน (หมายเหตุโปรแกรมเมอร์สามารถเปลี่ยนทั้งหมดนี้เมื่อเขียนโปรแกรม)

ดังนั้นสิ่งที่ nohup ทำคือให้กระบวนการเด็กแยกสภาพแวดล้อม I / O โดยแยกสิ่งที่ไม่เกี่ยวข้องกับเปลือกหอยและป้องกันเด็กจากสัญญาณ SIGHUP เมื่อผู้ใช้ยกเลิกการเชื่อมต่อคุณจะเห็นกระบวนการพื้นหลัง nohup เป็นเจ้าของโดย init (กระบวนการ 1) ไม่ใช่เชลล์ของผู้ใช้

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


สมมติว่าฉันใช้บันทึกเทอร์มินัล ssh ในเครื่องจากนั้นใช้เทอร์มินัล ssh เพื่อดำเนินการคำสั่ง (สมมติว่าเป็นกระบวนการระยะยาว) ถ้าฉันออกจากเซสชันเทอร์มินัลกระบวนการระยะยาวของคำสั่งจะถูกต้อง และถ้าฉันต้องการให้คำสั่งดำเนินการต่อไปแม้ว่าฉันจะออกจาก shell ฉันควรใช้ nohup หรือ & (ที่ส่วนท้ายของคำสั่ง) หรือใช้ทั้ง nohup และ &?
George2

1
ถูกต้องใช้ทั้ง nohup และ & สำหรับกระบวนการเพื่อดำเนินการต่อหลังจากยกเลิกการเชื่อมต่อ SSH
kmarsh

ขอบคุณ Kmarsh! ฉันต้องการทราบว่าทำไมเราต้องใช้ทั้ง & และ nohup และฟังก์ชั่นส่วนบุคคลของพวกเขาที่ทำให้เราบรรลุเป้าหมายในการปล่อยให้คำสั่งทำงานต่อไปแม้ว่าคอนโซลเทอร์มินัลจะหยุดทำงาน ฉันอ่าน man page สำหรับ nohup และมีการกล่าวถึง "เรียกใช้คำสั่งภูมิคุ้มกันต่อ hangups ด้วยผลลัพธ์ที่ไม่ใช่ tty" ฉันสับสนว่าภูมิคุ้มกันต่อ hangups เป็นสิ่งที่คุณหมายถึงการให้คำสั่งยังคงทำงานโดยไม่ได้รับผลกระทบจากการเลิก เทอร์มินัลคอนโซล ถ้าเป็นเช่นนั้นฉันคิดว่าการใช้ nohup ก็เพียงพอแล้วและไม่จำเป็นต้องใช้ & มีคำแนะนำอะไรมั้ย?
George2

1
ฉันจะแก้ไขคำตอบเพื่อตอบ
kmarsh

13

นอกจากนี้ในการตอบ @ มาร์ติน: การใช้งานอื่น ๆ ของเครื่องหมาย ( >&เหนือ) คือการจับทั้งสอง และstdout stderrโดยปกติหากคุณเปลี่ยนเส้นทางไปยังไฟล์ที่มีเพียง '>' คุณจะได้รับผลลัพธ์stdoutโดยไม่มีข้อผิดพลาดใด ๆ


1. ขอบคุณ Ash ฉันต้องการยืนยันกับคุณว่า "> & <ชื่อไฟล์บันทึก>" จะถ่ายโอน stderr และ stdout ทั้งหมดไปยังไฟล์บันทึกถูกต้องหรือไม่ 2. และการใช้ "> <ชื่อไฟล์บันทึก>" จะถ่ายโอน stdout ทั้งหมดไปยังไฟล์บันทึกถูกต้องหรือไม่
George2

1
@ George: ใช่ถูกต้อง
Ash

ขอบคุณ Ash! ฉันต้องการทราบว่าทำไมเราต้องใช้ทั้ง & และ nohup และฟังก์ชั่นส่วนบุคคลของพวกเขาที่ทำให้เราบรรลุเป้าหมายในการปล่อยให้คำสั่งทำงานต่อไปแม้ว่าคอนโซลเทอร์มินัลจะหยุดทำงาน ฉันอ่าน man page สำหรับ nohup และมีการกล่าวถึง "เรียกใช้คำสั่งภูมิคุ้มกันต่อ hangups ด้วยผลลัพธ์ที่ไม่ใช่ tty" ฉันสับสนว่าภูมิคุ้มกันต่อ hangups เป็นสิ่งที่คุณหมายถึงการให้คำสั่งยังคงทำงานโดยไม่ได้รับผลกระทบจากการเลิก เทอร์มินัลคอนโซล ถ้าเป็นเช่นนั้นฉันคิดว่าการใช้ nohup ก็เพียงพอแล้วและไม่จำเป็นต้องใช้ & มีคำแนะนำอะไรมั้ย?
George2

4

นอกจากคำตอบของ Martin and Ash บางครั้งคุณอาจเห็นการใช้&&โทเค็น ใช้เพื่อบอกว่า "เรียกใช้คำสั่งที่สองถ้าหากคำสั่งแรกรันเสร็จสมบูรณ์" คำสั่งที่เขียนได้ดีหากมีข้อผิดพลาดไม่ออกจากระบบ

[kevin@box ~]$ ls file && echo removing file && rm file
ls: file: No such file or directory
[kevin@box ~]$ touch file
[kevin@box ~]$ ls file && echo removing file && rm file
file
removing file
[kevin@box ~]$

เจ๋งเควิน! สมมติว่าฉันใช้บันทึกเทอร์มินัล ssh ในเครื่องจากนั้นใช้เทอร์มินัล ssh เพื่อดำเนินการคำสั่ง (สมมติว่าเป็นกระบวนการระยะยาว) ถ้าฉันออกจากเซสชันเทอร์มินัลกระบวนการระยะยาวของคำสั่งจะถูกต้อง และถ้าฉันต้องการให้คำสั่งดำเนินการต่อไปแม้ว่าฉันจะออกจาก shell ฉันควรใช้ nohup หรือ & (ที่ส่วนท้ายของคำสั่ง) หรือใช้ทั้ง nohup และ &?
George2

ทั้งสองจะทำงาน NOHUP เป็นวิธีดั้งเดิมในการทำฉันจินตนาการ (แต่ฉันคาดเดาทั้งหมด) แต่พื้นหลังใช้งานได้ในขณะนี้ ข้อแตกต่างที่สำคัญคือเมื่อใช้งานเชลล์แบบโต้ตอบโดย sshing เข้าสู่ระบบรีโมต กระบวนการ NOHUP จะทำงานในเบื้องหน้า แต่จะยังคงทำงานหากคุณออกในขณะที่กระบวนการพื้นหลังจะกลับมาทันทีหลังจากที่คุณวางคำสั่ง แต่เมื่อคุณพยายามออกจากเชลล์เชิงโต้ตอบโดยมีคำสั่งที่ทำงานในพื้นหลังคุณจะได้รับคำเตือนก่อน
Kevin M

2

คำตอบของ Martin นั้นดี แต่ค่อนข้างคลุมเครือ คำสั่งจะถูก fork'ed และดำเนินการเสมอ แต่ลักษณะการทำงานของเชลล์ปกติคือรอคำสั่งจนกว่าจะออก เครื่องหมายแอมเปอร์แซนด์ใส่ไว้ในพื้นหลังเพื่อให้คุณได้รับการแจ้งเตือนจากเครื่องปลายทางและคุณสามารถทำสิ่งอื่นได้ หากกระบวนการแยกข้อมูลออกเป็น stdout หรือ stderr สิ่งนี้จะถูกรวมเข้ากับสิ่งที่คุณทำที่พรอมต์และอาจทำให้คุณสับสน นี่คือสาเหตุที่คุณเปลี่ยนเส้นทางด้วย> & /path/to/logfile.txt

ในการตอบสนองต่อ George2 พฤติกรรมปกติสำหรับการออกจากเชลล์คือการส่งสัญญาณ SIGHUP ไปยังกระบวนการทั้งหมดในกลุ่มกระบวนการเดียวกัน หากคุณต้องการให้สิ่งนี้ดำเนินต่อไปแม้ว่าคุณจะปิดกระบวนการเชลล์คุณสามารถใช้คำสั่ง nohup เพื่อทำให้พวกเขาเพิกเฉยต่อสัญญาณนี้และทำงานต่อไป มีชื่อพิเศษสำหรับกระบวนการประเภทนี้เรียกว่ากระบวนการ daemon (ออกเสียงว่า "อสูร")


ขอบคุณมาก! สมมติว่าฉันใช้บันทึกเทอร์มินัล ssh ในเครื่องจากนั้นใช้เทอร์มินัล ssh เพื่อดำเนินการคำสั่ง (สมมติว่าเป็นกระบวนการระยะยาว) ถ้าฉันออกจากเซสชันเทอร์มินัลกระบวนการระยะยาวของคำสั่งจะถูกต้อง และถ้าฉันต้องการให้คำสั่งดำเนินการต่อไปแม้ว่าฉันจะออกจาก shell ฉันควรใช้ nohup หรือ & (ที่ส่วนท้ายของคำสั่ง) หรือใช้ทั้ง nohup และ &? และทำไม?
George2

เฮ้จอร์จขอโทษด้วยที่ฉันตอบช้ามาก ใช่ถ้าคุณออกจากเชลล์กระบวนการในระยะยาวจะถูกยกเลิก หากคุณต้องการให้มันดำเนินต่อไปคุณต้องทำทั้งสองอย่างโดยไม่มีการหยุดทำงาน (เพื่อไม่ให้มันจบลงเมื่อเชลล์ปิด) และ & (เพื่อใส่พื้นหลังเพื่อให้คุณสามารถ Crtl-D หรือออกจากเปลือกของคุณ) คุณยังสามารถดูคำสั่ง setsid ซึ่งจะทำให้กระบวนการของคุณทำงานโดยไม่สนใจ SIGHUP ด้วยวิธีที่แตกต่างกันเล็กน้อย
Rich Homolka

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