ฉันมีกระบวนการที่ทำงานมาแล้วเป็นเวลานานและไม่ต้องการจบมัน
ฉันจะวางไว้ใต้ nohup ได้อย่างไร (นั่นคือฉันจะทำให้มันทำงานต่อไปได้อย่างไรแม้ว่าฉันจะปิดเครื่อง?)
ฉันมีกระบวนการที่ทำงานมาแล้วเป็นเวลานานและไม่ต้องการจบมัน
ฉันจะวางไว้ใต้ nohup ได้อย่างไร (นั่นคือฉันจะทำให้มันทำงานต่อไปได้อย่างไรแม้ว่าฉันจะปิดเครื่อง?)
คำตอบ:
การใช้Job Control of bash เพื่อส่งกระบวนการไปยังพื้นหลัง:
bg
เพื่อรันในพื้นหลังdisown -h [job-spec]
โดยที่ [job-spec] คือหมายเลขงาน (เช่น%1
สำหรับงานแรกที่ทำงานค้นหาเกี่ยวกับหมายเลขของคุณด้วยjobs
คำสั่ง) เพื่อให้งานไม่ถูกฆ่าเมื่อปิดเทอร์มินัลdisown -h
อาจเป็นคำตอบที่ถูกต้องมากขึ้น: "ทำให้การปฏิเสธไม่ทำงานเหมือน nohup (เช่นงานจะอยู่ในแผนผังกระบวนการเชลล์ปัจจุบันของคุณจนกว่าคุณจะออกจากเชลล์) สิ่งนี้ช่วยให้คุณเห็น งานทั้งหมดที่เชลล์นี้เริ่ม " (จาก [ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/ … )
disown
, disown ทำให้กระบวนการ daemon ซึ่งหมายความว่าอินพุต / เอาต์พุตมาตรฐานถูกเปลี่ยนเส้นทางไปยัง / dev / null ดังนั้นหากคุณวางแผนที่จะปฏิเสธงานควรเริ่มต้นด้วยการเข้าสู่ไฟล์เช่นmy_job_command | tee my_job.log
disown
ยกเลิกการเชื่อมโยงท่อใด ๆ ออกจากกระบวนการ หากต้องการติดตั้งท่ออีกครั้งให้ใช้gdb
ตามที่อธิบายไว้ในชุดข้อความนี้ โดยเฉพาะโพสต์นี้
สมมติว่าด้วยเหตุผลบางอย่างCtrl+ Zยังไม่ทำงานให้ไปที่เทอร์มินัลอื่นค้นหา id กระบวนการ (โดยใช้ps
) และเรียกใช้:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOP
จะระงับกระบวนการและSIGCONT
จะดำเนินการตามกระบวนการในพื้นหลัง ดังนั้นตอนนี้การปิดเทอร์มินัลทั้งสองจะไม่หยุดกระบวนการของคุณ
disown %1
ในเทอร์มินัลแรกก่อนที่จะปิด
kwin
หลังจากเกิดความผิดพลาดโดยไม่คิดถึงผลที่ตามมา) ดังนั้นถ้าฉันหยุด kwin ทุกอย่างจะแข็งและฉันก็ไม่มีทางวิ่งได้bg
!
คำสั่งเพื่อแยกงานที่กำลังรันอยู่จากเชลล์ (= ทำให้ไม่มีงาน) คือ disown
และคำสั่งพื้นฐานของเชลล์
จาก bash-manpage (man bash):
ปฏิเสธ [-ar] [-h] [jobspec ... ]
หากไม่มีตัวเลือกงานแต่ละงานจะถูกลบออกจากตารางของงานที่ใช้งานอยู่ หากกำหนดตัวเลือก -h แต่ละงานจะไม่ถูกลบออกจากตาราง แต่ทำเครื่องหมายเพื่อให้ SIGHUP ไม่ได้ถูกส่งไปยังงานหากเชลล์ได้รับ SIGHUP หากไม่มี jobspec และไม่มีการระบุอ็อพชัน -a หรือ -r งานปัจจุบันจะถูกใช้ หากไม่มีการระบุ jobspec ตัวเลือก -a หมายถึงการลบหรือทำเครื่องหมายงานทั้งหมด อ็อพชัน -r โดยไม่มีอาร์กิวเมนต์ jobspec จำกัด การดำเนินการกับการรันงาน ค่าส่งคืนคือ 0 เว้นแต่ jobspec ไม่ได้ระบุงานที่ถูกต้อง
นั่นหมายความว่าง่าย
disown -a
จะลบงานทั้งหมดออกจากตารางงานและทำให้ไม่มีงานทำ
disown -a
ลบงานทั้งหมด ง่ายdisown
ลบงานปัจจุบันเท่านั้น ในฐานะที่เป็นหน้าคนในคำตอบพูดว่า
เหล่านี้เป็นคำตอบที่ดีข้างต้นฉันแค่ต้องการเพิ่มความกระจ่าง:
คุณไม่สามารถdisown
pid หรือกระบวนการคุณdisown
เป็นงานและนั่นคือความแตกต่างที่สำคัญ
งานเป็นสิ่งที่เป็นความคิดของกระบวนการที่แนบมากับเชลล์ดังนั้นคุณต้องโยนงานลงในพื้นหลัง (ไม่ระงับ) และปฏิเสธมัน
ปัญหา:
% jobs
[1] running java
[2] suspended vi
% disown %1
ดูhttp://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ สำหรับการสนทนาอย่างละเอียดของ Unix Job Control
น่าเสียดายที่disown
มีเฉพาะในการทุบตีและไม่สามารถใช้ได้ในทุกกระสุน
รสชาติบางอย่างของ Unix (เช่น AIX และ Solaris) มีตัวเลือกในnohup
คำสั่งซึ่งสามารถนำไปใช้กับกระบวนการที่กำลังทำงานอยู่:
nohup -p pid
AIX
Solaris
"nohup เวอร์ชัน AIX และ Solaris มีตัวเลือก -p ที่ปรับเปลี่ยนกระบวนการที่กำลังทำงานอยู่เพื่อละเว้นสัญญาณ SIGHUP ในอนาคตซึ่งแตกต่างจากตัวสร้าง disin ของ bash ที่อธิบายไว้ข้างต้น nohup -p ยอมรับรหัสกระบวนการ" แหล่งที่มา
คำตอบของโหนดนั้นยอดเยี่ยมจริง ๆ แต่เหลือเปิดคำถามว่าจะเปลี่ยน stdout และ stderr ได้อย่างไร ฉันพบวิธีแก้ปัญหาบนUnix & Linuxแต่ก็ยังไม่สมบูรณ์ ฉันต้องการรวมสองวิธีนี้เข้าด้วยกัน นี่มันคือ:
สำหรับการทดสอบของฉันฉันได้สร้างสคริปต์ทุบตีเล็ก ๆ ชื่อว่า loop.sh ซึ่งพิมพ์ pid ของตัวเองด้วยการนอนหลับเป็นนาทีในวงวนไม่สิ้นสุด
$./loop.sh
ตอนนี้รับ PID ของกระบวนการนี้อย่างใด มักจะps -C loop.sh
จะดีพอ แต่มันถูกพิมพ์ในกรณีของฉัน
ตอนนี้เราสามารถสลับไปยังเทอร์มินัลอื่น (หรือกด ^ Z และในเทอร์มินัลเดียวกัน) ตอนนี้gdb
ควรแนบกับกระบวนการนี้
$ gdb -p <PID>
สิ่งนี้จะหยุดสคริปต์ (หากทำงาน) สามารถตรวจสอบสถานะได้โดยps -f <PID>
ที่STAT
ฟิลด์คือ 'T +' (หรือในกรณีที่ ^ Z 'T') ซึ่งหมายถึง (man ps (1))
T Stopped, either by a job control signal or because it is being traced
+ is in the foreground process group
(gdb) call close(1)
$1 = 0
ปิด (1) ส่งคืนศูนย์เมื่อสำเร็จ
(gdb) call open("loop.out", 01102, 0600)
$6 = 1
Open (1) ส่งคืน file descriptor ใหม่ถ้าสำเร็จ
open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
เปิดนี้เป็นที่เท่าเทียมกันกับ แทนที่จะO_RDWR
O_WRONLY
สามารถนำไปใช้ แต่/usr/sbin/lsof
พูดว่า 'U' สำหรับ STD ทั้งหมด * ขนย้ายไฟล์ ( FD
คอลัมน์) O_RDWR
ซึ่งเป็น
ฉันตรวจสอบค่าในไฟล์ /usr/include/bits/fcntl.h
ไฟล์เอาต์พุตสามารถเปิดได้O_APPEND
เช่นเดียวกับที่nohup
ทำ แต่ไม่แนะนำโดยman open(2)
เนื่องจากปัญหา NFS ที่เป็นไปได้
หากเราได้รับ -1 เป็นค่าตอบแทนแล้วcall perror("")
พิมพ์ข้อความผิดพลาด หากเราต้องการ errno ให้ใช้p errno
gdb comand
ตอนนี้เราสามารถตรวจสอบไฟล์ที่เปลี่ยนเส้นทางใหม่ /usr/sbin/lsof -p <PID>
พิมพ์:
loop.sh <PID> truey 1u REG 0,26 0 15008411 /home/truey/loop.out
หากเราต้องการเราสามารถเปลี่ยนเส้นทาง stderr ไปยังไฟล์อื่นหากเราต้องการใช้call close(2)
และcall open(...)
อีกครั้งโดยใช้ชื่อไฟล์อื่น
ตอนนี้ไฟล์แนบbash
จะต้องมีการเปิดตัวและเราสามารถออกจากgdb
:
(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q
หากสคริปต์หยุดทำงานโดยgdb
เทอร์มินัลอื่นสคริปต์จะยังคงทำงานต่อไป เราสามารถสลับกลับไปที่เทอร์มินัลของ loop.sh ตอนนี้มันไม่ได้เขียนอะไรไปยังหน้าจอ แต่ทำงานและเขียนลงในไฟล์ เราต้องใส่มันเข้าไปในพื้นหลัง ดังนั้นกด^Z
ดังนั้นกด
^Z
[1]+ Stopped ./loop.sh
(ตอนนี้เราอยู่ในสถานะเดียวกันกับถ้า ^Z
ถูกกดที่จุดเริ่มต้น)
ตอนนี้เราสามารถตรวจสอบสถานะของงาน:
$ ps -f 24522
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID><PPID> 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh
$ jobs
[1]+ Stopped ./loop.sh
ดังนั้นกระบวนการควรทำงานในพื้นหลังและแยกออกจากเทอร์มินัล จำนวนในการออกคำสั่งในวงเล็บระบุภายในงานjobs
bash
เราสามารถใช้bash
คำสั่งบิวด์อินต่อไปนี้ที่ใช้เครื่องหมาย '%' หน้าหมายเลขงาน:
$ bg %1
[1]+ ./loop.sh &
$ disown -h %1
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID><PPID> 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh
และตอนนี้เราสามารถออกจากการเรียกทุบตี กระบวนการทำงานต่อเนื่องในพื้นหลัง ถ้าเราออกจาก PPID กลายเป็น 1 (init (1) กระบวนการ) และเทอร์มินัลการควบคุมไม่เป็นที่รู้จัก
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID> 1 0 11:16 ? S 0:00 /bin/bash ./loop.sh
$ /usr/bin/lsof -p <PID>
...
loop.sh <PID> truey 0u CHR 136,36 38 /dev/pts/36 (deleted)
loop.sh <PID> truey 1u REG 0,26 1127 15008411 /home/truey/loop.out
loop.sh <PID> truey 2u CHR 136,36 38 /dev/pts/36 (deleted)
แสดงความคิดเห็น
สิ่ง gdb สามารถ automatized สร้างไฟล์ (เช่น loop.gdb) gdb -q -x loop.gdb -p <PID>
ที่มีคำสั่งและเรียกใช้ loop.gdb ของฉันมีลักษณะเช่นนี้:
call close(1)
call open("loop.out", 01102, 0600)
# call close(2)
# call open("loop.err", 01102, 0600)
detach
quit
หรือหนึ่งสามารถใช้หนึ่งซับต่อไปนี้แทน:
gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>
ฉันหวังว่านี่เป็นคำอธิบายที่สมบูรณ์ของวิธีแก้ปัญหา
lsof
(ชื่อของตัวจัดการไฟล์นั้นpipe
ไม่เหมือน/dev/pts/1
) หรือโดยls -l /proc/<PID>/fd/<fd>
(นี่จะแสดง symlink ของหมายเลขอ้างอิง) ด้วยกระบวนการย่อยยังคงไม่สามารถเปลี่ยนเส้นทางผลลัพธ์ซึ่งควรเปลี่ยนเส้นทางไปยังไฟล์
ในการส่งกระบวนการทำงานไปที่ nohup ( http://en.wikipedia.org/wiki/Nohup )
nohup -p pid
มันไม่ได้ผลสำหรับฉัน
จากนั้นฉันลองคำสั่งต่อไปนี้และมันก็ใช้ได้ดีมาก
เรียก somecommand /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
บางพูด
Ctrl+ Zเพื่อหยุด (หยุด) โปรแกรมและกลับไปที่เชลล์
bg
เพื่อรันในพื้นหลัง
disown -h
เพื่อไม่ให้กระบวนการถูกทำลายเมื่อเทอร์มินัลปิด
พิมพ์exit
เพื่อออกจากเชลล์เพราะตอนนี้คุณทำได้ดีเพราะการดำเนินการจะทำงานในพื้นหลังในกระบวนการของตัวเองดังนั้นจึงไม่ได้เชื่อมโยงกับเชลล์
nohup SOMECOMMAND
กระบวนการนี้เป็นเทียบเท่าของการทำงาน
บนระบบ AIX ของฉันฉันพยายามแล้ว
nohup -p processid>
มันใช้งานได้ดี มันยังคงเรียกใช้กระบวนการของฉันแม้หลังจากปิดหน้าต่างเทอร์มินัล เรามี ksh เป็นเชลล์เริ่มต้นดังนั้นคำสั่งbg
และdisown
ไม่ทำงาน
bg
- สิ่งนี้จะทำให้งานอยู่ในพื้นหลังและกลับมาในกระบวนการทำงานdisown -a
- สิ่งนี้จะตัดสิ่งที่แนบมาทั้งหมดกับงาน (เพื่อให้คุณสามารถปิดเครื่องและมันจะยังคงทำงาน)ขั้นตอนง่าย ๆ เหล่านี้จะช่วยให้คุณปิดเทอร์มินัลขณะที่กระบวนการทำงานต่อไป
มันจะไม่ใส่nohup
(ขึ้นอยู่กับความเข้าใจในคำถามของคุณคุณไม่ต้องการที่นี่)
สิ่งนี้ใช้ได้กับฉันบน Ubuntu Linux ในขณะที่อยู่ใน tcshell
CtrlZ เพื่อหยุดชั่วคราว
bg
เพื่อทำงานในพื้นหลัง
jobs
เพื่อรับหมายเลขงาน
nohup %n
โดยที่ n คือหมายเลขงาน
nohup: failed to run command '%1': No such file or directory
yourExecutable &
และเอาท์พุทยังคงปรากฏบนหน้าจอและCtrl+C
ดูเหมือนจะไม่หยุดอะไรเลยเพียงแค่พิมพ์สุ่มสี่สุ่มห้าdisown;
และกดEnter
แม้ว่าหน้าจอจะเลื่อนด้วยเอาท์พุท คุณกำลังพิมพ์ กระบวนการจะถูกปฏิเสธและคุณจะสามารถปิดเครื่องได้โดยไม่ต้องเสียกระบวนการ