ฉันจะใช้คำสั่ง nohup โดยไม่รับ nohup.out ได้อย่างไร


309

ฉันมีปัญหากับคำสั่ง nohup

เมื่อฉันทำงานฉันมีข้อมูลมากมาย nohup.out เอาต์พุตมีขนาดใหญ่เกินไปและกระบวนการของฉันช้าลง ฉันจะรันคำสั่งนี้โดยไม่รับ nohup.out ได้อย่างไร?


คำตอบ:


612

nohupคำสั่งเพียงเขียนไปnohup.outถ้าการส่งออกมิฉะนั้นจะไปยังสถานี หากคุณเปลี่ยนเส้นทางผลลัพธ์ของคำสั่งที่อื่น - รวมถึง/dev/null- นั่นคือสิ่งที่มันจะไปแทน

 nohup command >/dev/null 2>&1   # doesn't create nohup.out

หากคุณกำลังใช้nohupนั่นอาจหมายถึงคุณต้องการเรียกใช้คำสั่งในพื้นหลังโดยใส่คำสั่งไว้&ท้ายสิ่งทั้งหมด:

 nohup command >/dev/null 2>&1 & # runs in background, still doesn't create nohup.out

บน Linux การรันงานด้วยnohupการปิดอินพุตโดยอัตโนมัติเช่นกัน บนระบบอื่น ๆ สะดุดตา BSD และ macOS ซึ่งไม่ใช่กรณีดังนั้นเมื่อทำงานในพื้นหลังคุณอาจต้องการปิดอินพุตด้วยตนเอง แม้ว่าอินพุตปิดจะไม่มีผลต่อการสร้างหรือไม่nohup.outก็ตาม แต่จะช่วยหลีกเลี่ยงปัญหาอื่น: หากกระบวนการแบ็คกราวน์พยายามอ่านอะไรจากอินพุตมาตรฐานมันจะหยุดชั่วคราวรอให้คุณนำกลับมาที่พื้นหน้าและพิมพ์บางอย่าง ดังนั้นเวอร์ชันที่ปลอดภัยเป็นพิเศษจะมีลักษณะดังนี้:

nohup command </dev/null >/dev/null 2>&1 & # completely detached from terminal 

อย่างไรก็ตามโปรดทราบว่าสิ่งนี้ไม่ได้ป้องกันคำสั่งจากการเข้าถึงเทอร์มินัลโดยตรงและไม่ได้ลบมันออกจากกลุ่มกระบวนการเชลล์ของคุณ หากคุณต้องการทำสิ่งหลังและคุณกำลังรัน bash, ksh หรือ zsh คุณสามารถทำได้โดยการรันdisownโดยไม่มีอาร์กิวเมนต์เป็นคำสั่งถัดไป นั่นหมายความว่ากระบวนการพื้นหลังจะไม่เชื่อมโยงกับเชลล์ "งาน" อีกต่อไปและจะไม่มีสัญญาณใด ๆ ที่ส่งต่อไปยังเชลล์จากเชลล์ (สังเกตความแตกต่าง: disownกระบวนการ ed จะไม่ส่งสัญญาณใด ๆ ไปยังมันโดยอัตโนมัติโดยพาเรนต์เชลล์ - แต่หากไม่มีnohupก็จะยังคงได้รับHUPสัญญาณที่ส่งผ่านวิธีอื่นเช่นkillคำสั่งด้วยตนเองnohupกระบวนการ ed จะละเว้นHUPสัญญาณใด ๆไม่ว่าพวกเขาจะถูกส่งอย่างไร)

คำอธิบาย:

ในระบบ Unixy แหล่งที่มาของอินพุตหรือเป้าหมายของเอาต์พุตมีตัวเลขที่เกี่ยวข้องกับมันเรียกว่า "file descriptor" หรือ "fd" ทุกโปรแกรมที่กำลังทำงานอยู่ ("กระบวนการ") มีชุดของตัวเองและเมื่อกระบวนการใหม่เริ่มขึ้นก็มีสามของพวกเขาเปิดแล้ว: "อินพุตมาตรฐาน" ซึ่งเป็น fd 0 เปิดให้กระบวนการอ่านจากในขณะที่ "เอาต์พุตมาตรฐาน" (fd 1) และ "ข้อผิดพลาดมาตรฐาน" (fd 2) เปิดขึ้นเพื่อให้เขียนได้ หากคุณเพียงแค่เรียกใช้คำสั่งในหน้าต่างเทอร์มินัลตามค่าเริ่มต้นสิ่งที่คุณพิมพ์จะไปที่อินพุตมาตรฐานในขณะที่ทั้งเอาต์พุตมาตรฐานและข้อผิดพลาดมาตรฐานจะถูกส่งไปที่หน้าต่างนั้น

แต่คุณสามารถขอให้เชลล์เปลี่ยนจุดบ่งไฟล์ใด ๆ หรือทั้งหมดก่อนที่จะเรียกใช้คำสั่ง นั่นคือสิ่งที่เปลี่ยนเส้นทาง ( <, <<, >, >>) และท่อ ( |) ผู้ประกอบการทำ

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

โอเปอเรเตอร์การเปลี่ยนเส้นทางนั้นมีความเป็นมิตรมากกว่าซึ่งจะช่วยให้คุณระบุไฟล์ descriptor ที่จะเปลี่ยนทิศทาง ดังนั้น0<infileอ่านเข้ามาตรฐานจากไฟล์ที่มีชื่อinfileในขณะที่ผนวกข้อผิดพลาดมาตรฐานที่ส่วนท้ายของไฟล์ที่มีชื่อ2>>logfile logfileหากคุณไม่ได้ระบุจำนวนดังนั้นค่าเริ่มต้นการเปลี่ยนเส้นทางอินพุตเป็น fd 0 ( <เหมือนกับ0<) ในขณะที่การเปลี่ยนเส้นทางออกเป็นค่าเริ่มต้นเป็น fd 1 ( >เหมือนกับ1>)

นอกจากนี้คุณสามารถรวมไฟล์ descriptors เข้าด้วยกัน: 2>&1หมายถึง "ส่งข้อผิดพลาดมาตรฐานทุกที่ที่เอาต์พุตมาตรฐานกำลังดำเนินการ" นั่นหมายความว่าคุณจะได้รับเอาต์พุตสตรีมเดียวที่มีทั้งข้อผิดพลาดมาตรฐานและมาตรฐานที่ผสมกันโดยไม่มีวิธีแยกพวกเขาอีกต่อไป แต่ก็หมายความว่าคุณสามารถรวมข้อผิดพลาดมาตรฐานในไพพ์ได้

ดังนั้นลำดับจึง>/dev/null 2>&1หมายถึง "ส่งเอาต์พุตมาตรฐานไปยัง/dev/null" (ซึ่งเป็นอุปกรณ์พิเศษที่เพิ่งทิ้งสิ่งที่คุณเขียนไป) "จากนั้นส่งข้อผิดพลาดมาตรฐานไปยังที่ใดก็ตามที่เอาต์พุตมาตรฐานกำลังดำเนินการ" (ซึ่งเราเพิ่งแน่ใจว่าเป็น/dev/null) โดยพื้นฐานแล้ว "ทิ้งคำสั่งใดก็ตามที่เขียนไปยัง file descriptor"

เมื่อnohupตรวจพบว่าไม่มีข้อผิดพลาดมาตรฐานหรือเอาท์พุทเชื่อมต่อกับเทอร์มินัลก็ไม่ได้กังวลที่จะสร้างnohup.outแต่สมมติว่าเอาท์พุทจะถูกเปลี่ยนเส้นทางแล้วที่ผู้ใช้ต้องการไป

/dev/nullอุปกรณ์ทำงานสำหรับการป้อนข้อมูลมากเกินไป; หากคุณเรียกใช้คำสั่งด้วย</dev/nullความพยายามใด ๆ ที่คำสั่งให้อ่านจากอินพุตมาตรฐานจะพบจุดสิ้นสุดไฟล์ทันที โปรดทราบว่าไวยากรณ์การผสานจะไม่มีผลเหมือนกันที่นี่ มันจะทำงานเพื่อชี้ไฟล์ descriptor ไปยังอีกอันที่เปิดในทิศทางเดียวกัน (อินพุตหรือเอาต์พุต) เชลล์จะยอมให้คุณทำ>/dev/null <&1แต่สิ่งนี้จะสร้างกระบวนการด้วยตัวอธิบายไฟล์อินพุตที่เปิดบนเอาต์พุตสตรีมดังนั้นแทนที่จะเพียงแค่กดจุดสิ้นสุดของไฟล์ความพยายามในการอ่านใด ๆ จะทำให้เกิดข้อผิดพลาด


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

1
@Tim - คำตอบนั้นถูกต้องสำหรับ Linux แต่ไม่ใช่สำหรับ BSD หรือ OS X ซึ่ง nohupไม่ได้ปิดอินพุตมาตรฐานโดยอัตโนมัติ โปรดทราบว่าnohupไม่ใช่เชลล์ในตัว แต่เป็นยูทิลิตี้ไบนารี
Mark Reed

nohup เป็นส่วนหนึ่งของ coreutils คุณหมายถึงการนำไปใช้nohupนั้นแตกต่างกันสำหรับ linux และสำหรับ BSD หรือ OS X หรือไม่?
ทิม

ใช่. ชื่อ "coreutils" หมายถึงแพ็คเกจ GNU แต่ BSD, OS X, SmartOS / Illumos และ Unixes เชิงพาณิชย์จำนวนมาก - โดยทั่วไปผู้ที่อยู่นานกว่า GNU - มียูทิลิตี้หลักที่ไม่ใช่ GNU awkมีความแตกต่างsedมีความแตกต่างแตกต่างnohupกัน ...
Mark Reed

คุณไม่เขียน "ความปลอดภัยเป็นพิเศษ" ทำไมโดย</dev/null? ดู0>/dev/null unix.stackexchange.com/a/266247
Tim

68
nohup some_command > /dev/null 2>&1&

นั่นคือทั้งหมดที่คุณต้องทำ!


4
มีคำตอบอื่นที่เกือบจะมีสิ่งนี้เหมือนกัน แต่พวกเขาไม่มี "&" พิเศษในตอนท้าย
11101101b

10
การ&ที่จะทำให้คุณไม่จำเป็นต้องใช้ctrl-cหากมีความสำคัญกับคุณ
SunSparc

1
ความสามารถในการทำงานใน BG มีประโยชน์มาก
ist_lion

สิ่งนี้มีประโยชน์เฉพาะในกรณีที่คุณไม่ต้องวุ่นวายกับการจับsome_commandเอาท์พุทรวมถึงข้อผิดพลาด
wulfgarpro

12

คุณลองเปลี่ยนเส้นทางสตรีม I / O ทั้งสาม:

nohup ./yourprogram > foo.out 2> foo.err < /dev/null &

1
ไม่ควรเป็น>/ dev / null แทนที่จะเป็น </ dev / null?
Scott Chu

3
@ScottChu เปลี่ยนเส้นทางเข้ามาตรฐานสำหรับ< /dev/null nohupLinux ไม่ต้องการสิ่งนี้ แต่ POSIX อนุญาตให้มีพฤติกรรมที่nohupไม่สามารถทำงานบนพื้นหลังหากอินพุตมาตรฐานเชื่อมต่อกับเทอร์มินัล ตัวอย่างของระบบดังกล่าวคือ BSD และ OS X.
Mikko Rantalainen

8

คุณอาจต้องการที่จะใช้โปรแกรม detach คุณใช้มันชอบnohupแต่มันไม่ได้สร้างบันทึกเอาท์พุทเว้นแต่คุณจะบอกให้ นี่คือหน้าคน:

NAME
       detach - run a command after detaching from the terminal

SYNOPSIS
       detach [options] [--] command [args]

       Forks  a  new process, detaches is from the terminal, and executes com‐
       mand with the specified arguments.

OPTIONS
       detach recognizes a couple of options, which are discussed below.   The
       special  option -- is used to signal that the rest of the arguments are
       the command and args to be passed to it.

       -e file
              Connect file to the standard error of the command.

       -f     Run in the foreground (do not fork).

       -i file
              Connect file to the standard input of the command.

       -o file
              Connect file to the standard output of the command.

       -p file
              Write the pid of the detached process to file.

EXAMPLE
       detach xterm

       Start an xterm that will not be closed when the current shell exits.

AUTHOR
       detach was written by Robbert Haarman.  See  http://inglorion.net/  for
       contact information.

หมายเหตุฉันไม่มีส่วนเกี่ยวข้องกับผู้เขียนโปรแกรม ฉันเป็นเพียงผู้ใช้ที่พึงพอใจของโปรแกรม


2
ลิงก์ไม่เสียหายและ repo คอมไพล์นั้นเก่า ไม่รวม v0.2.3 ปัจจุบัน
Dan D.

5

คำสั่งดังต่อไปนี้จะช่วยให้คุณเรียกใช้บางสิ่งบางอย่างในพื้นหลังโดยไม่ได้รับ nohup.out:

nohup command |tee &

ด้วยวิธีนี้คุณจะสามารถรับเอาต์พุตคอนโซลในขณะที่รันสคริปต์บนเซิร์ฟเวอร์ระยะไกล: ป้อนคำอธิบายรูปภาพที่นี่


4
sudo bash -c "nohup /opt/viptel/viptel_bin/log.sh $* &> /dev/null"  &

การเปลี่ยนเส้นทางเอาต์พุตของ sudo ทำให้ sudo ทำการ reask สำหรับรหัสผ่านดังนั้นจำเป็นต้องใช้กลไกที่น่าอึดอัดใจในการทำตัวแปรนี้


1

หากคุณมี BASH เชลล์บน mac / linux ของคุณต่อหน้าคุณลองทำตามขั้นตอนด้านล่างเพื่อทำความเข้าใจเกี่ยวกับการเปลี่ยนเส้นทางในทางปฏิบัติ:

สร้างสคริปต์ 2 บรรทัดชื่อ zz.sh

#!/bin/bash
echo "Hello. This is a proper command"
junk_errorcommand
  • เอาต์พุตของคำสั่ง echo เข้าสู่ STDOUT filestream (file descriptor 1)
  • เอาต์พุตของคำสั่ง error ไปที่ STDERR filestream (file descriptor 2)

ขณะนี้เพียงแค่เรียกใช้งานสคริปต์ส่งทั้ง STDOUT และ STDERR ไปที่หน้าจอ

./zz.sh

ตอนนี้เริ่มต้นด้วยการเปลี่ยนเส้นทางมาตรฐาน:

zz.sh > zfile.txt

ในข้างต้น "echo" (STDOUT) ไปที่ zfile.txt โดยที่ "error" (STDERR) แสดงขึ้นมาบนหน้าจอ

ด้านบนเป็นเช่นเดียวกับ:

zz.sh 1> zfile.txt

ตอนนี้คุณสามารถลองตรงข้ามและเปลี่ยนเส้นทาง "ข้อผิดพลาด" STDERR ไปยังไฟล์ คำสั่ง STDOUT จาก "echo" ไปที่หน้าจอ

zz.sh 2> zfile.txt

เมื่อรวมสองข้อข้างต้นเข้าด้วยกัน:

zz.sh 1> zfile.txt 2>&1

คำอธิบาย:

  • ที่หนึ่งส่ง STDOUT 1 ไปที่ zfile.txt
  • จากนั้นส่ง STDERR 2 ไปที่ STDOUT 1 เอง (โดยใช้ & 1 ตัวชี้)
  • ดังนั้นทั้ง 1 และ 2 จะเป็นไฟล์เดียวกัน (zfile.txt)

ในที่สุดคุณสามารถจัดเก็บสิ่งทั้งหมดไว้ใน คำสั่ง nohup &เพื่อรันในพื้นหลัง:

nohup zz.sh 1> zfile.txt 2>&1&

1

คุณสามารถเรียกใช้คำสั่งด้านล่าง

nohup <your command> & >  <outputfile> 2>&1 &

เช่นฉันมีคำสั่ง nohup ภายในสคริปต์

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