ฉันจะรันคำสั่งที่จะอยู่รอดได้อย่างไรปิดเทอร์มินัล


313

บางครั้งฉันต้องการเริ่มกระบวนการและลืมมันไป ถ้าฉันเริ่มต้นจากบรรทัดคำสั่งเช่นนี้

redshift

ฉันปิดเทอร์มินัลไม่ได้ไม่เช่นนั้นจะทำให้กระบวนการหยุดทำงาน ฉันสามารถเรียกใช้คำสั่งในลักษณะที่ฉันสามารถปิดเทอร์มินัลโดยไม่ฆ่ากระบวนการได้หรือไม่?


4
ไม่ใช่การติดตั้งเริ่มต้นใน distros ทั้งหมด แต่หน้าจอคือเพื่อนของคุณ: en.wikipedia.org/wiki/GNU_Screen
Zayne S Halsall

สำหรับทุกคนที่ประสบปัญหาเดียวกัน: โปรดจำไว้ว่าแม้ว่าคุณจะพิมพ์yourExecutable &และเอาท์พุทยังคงปรากฏบนหน้าจอและCtrl+Cดูเหมือนจะไม่หยุดอะไรเลยเพียงแค่พิมพ์สุ่มสี่สุ่มห้าdisown;และกดEnterแม้ว่าหน้าจอจะเลื่อนด้วยเอาท์พุท คุณกำลังพิมพ์ กระบวนการจะถูกปฏิเสธและคุณจะสามารถปิดเครื่องได้โดยไม่ต้องเสียกระบวนการ
Nav

คุณสามารถใช้หน้าจอมัลติเพล็เช่นtmux มันสามารถใช้ได้ผ่าน apt-get บนเครื่องอูบุนตู
Himanshu

คำตอบ:


311

หนึ่งใน 2 ต่อไปนี้ควรใช้งานได้:

$ nohup redshift &

หรือ

$ redshift &
$ disown

ดูต่อไปนี้สำหรับข้อมูลเพิ่มเติมเล็กน้อยเกี่ยวกับวิธีการทำงาน:


5
อันที่สอง ( redshift & disown) ใช้ได้กับฉันบน Ubuntu 10.10 ดูเหมือนว่าจะทำงานได้ดีวางทั้งหมดไว้ในบรรทัดเดียว มีเหตุผลใดที่ฉันไม่ควรทำเช่นนี้?
Matthew

4
@ Matthewth คนแรกควรจะทำงานได้ดีเหมือนกัน แต่มันก็ไม่ได้พื้นหลังเหมือนที่สอง (คุณอาจต้องการnohup redshift &เพื่อให้มันเป็นพื้นหลัง) และการวางที่สองในหนึ่งบรรทัดเป็นเรื่องปกติ แต่โดยปกติแล้วคุณจะแยกด้วย;( redshift &; disown)
Michael Mrozek

10
@Michael: ทั้งสอง;และ&เป็นตัวคั่นคำสั่งและมีความสำคัญเท่ากัน ข้อแตกต่างเพียงอย่างเดียวคือการทำงานแบบซิงโครนัสและแบบอะซิงโครนัส (ตามลำดับ) ไม่จำเป็นต้องใช้&;ในการตั้งค่าให้เป็นเพียงแค่&(มันใช้งานได้ แต่มันซ้ำซ้อนเล็กน้อย)
Chris Johnsen

4
คำตอบที่ดีอย่างใดอย่างหนึ่งอาจเพิ่มว่ามันจะเป็นความคิดที่ดีที่จะเปลี่ยนเส้นทาง stdout และ stderr เพื่อให้ terminal จะไม่ถูกสแปมด้วยการส่งออกแก้ปัญหา
Kim

12
นอกจากนี้ยังredshift &!จะปฏิเสธ redshift ทันที

143

หากโปรแกรมของคุณกำลังทำงานอยู่คุณสามารถหยุดมันชั่วคราวได้ด้วยCtrl-Zให้ดึงมันเข้าไปในพื้นหลังด้วยbgแล้วdisownทำดังนี้:

$ sleep 1000
^Z
[1]+  Stopped                 sleep 1000
$ bg
$ disown
$ exit

3
หลังจากปฏิเสธฉันจะอ่าน stdout ของกระบวนการทำงานอีกครั้งได้อย่างไร
Necktwi


1
สิ่งนี้ไม่ได้ผลสำหรับฉันด้วยเหตุผลบางอย่าง (centos)
เอียน

วิธีการฆ่ากระบวนการหลังจากขั้นตอนนี้?
Palak Darji

2
@necktwi disownไม่ได้ตัดการเชื่อมต่อ stdout หรือ stderr อย่างไรก็ตามnohupเช่นเดียวกับ>/dev/null(ยกเลิกการเชื่อมต่อมาตรฐาน) 2>/dev/null(ตัดการเชื่อมต่อข้อผิดพลาดมาตรฐาน) มัน ( disown) ยกเลิกการเชื่อมต่อการควบคุมงาน
ctrl-alt-delor

45

คำตอบที่ดีมีการโพสต์แล้วโดย @StevenD แต่ฉันคิดว่านี่อาจทำให้ชัดเจนขึ้นอีกเล็กน้อย

เหตุผลที่กระบวนการหยุดทำงานเมื่อสิ้นสุดการทำงานของเครื่องเทอร์มินัลคือกระบวนการที่คุณเริ่มต้นเป็นกระบวนการลูกของเทอร์มินัล เมื่อคุณปิดเทอร์มินัลสิ่งนี้จะฆ่ากระบวนการลูกเหล่านี้เช่นกัน คุณสามารถดูแผนผังกระบวนการด้วยpstreeเช่นเมื่อทำงานkate &ใน Konsole:

init-+
     ├─konsole─┬─bash─┬─kate───2*[{kate}]
     │         │      └─pstree
     │         └─2*[{konsole}]

ในการทำให้kateกระบวนการแยกออกจากkonsoleเมื่อคุณยุติkonsoleใช้nohupกับคำสั่งดังนี้:

nohup kate &

หลังจากปิดkonsoleแล้วpstreeจะมีลักษณะดังนี้:

init-+
     |-kate---2*[{kate}]

และkateจะอยู่รอด :)

อีกทางเลือกหนึ่งคือการใช้screen/ tmux/ byobuซึ่งจะทำให้เชลล์ทำงานอยู่โดยไม่ขึ้นกับเทอร์มินัล


ฉันมีปัญหากับวิธีการปฏิเสธ ปัจจุบันนี้ใช้งานได้สำหรับฉันดังนั้นการขึ้นลง ฉันก็ชอบเช่นนี้เพราะฉันสามารถ tail -f nohup.out เพื่อดูว่าเกิดอะไรขึ้น แต่ไม่ต้องกังวลเกี่ยวกับเซสชันของฉันล้มเหลว
Ian

27

คุณสามารถเรียกใช้กระบวนการเช่นนี้ในเทอร์มินัล

setsid process

สิ่งนี้จะเรียกใช้โปรแกรมในเซสชันใหม่ ตามที่อธิบายไว้แล้วhttp://hanoo.org/index.php?article=run-program-in-new-session-linux


1
สิ่งใดที่คุณเห็นว่าเป็นข้อดีของ setsid over nohup?
itsbruce

1
1) nohup.outมันไม่ได้พิมพ์ข้อความที่น่ารำคาญเกี่ยวกับ 2) jobsมันไม่ได้อยู่ในรายการงานที่เปลือกของคุณจึงไม่ถ่วงการส่งออกของ
มิเคล

นี่เป็นทางออกเดียวที่ทำงานกับสคริปต์ที่ทำงานใน lxterminal เรียกใช้ pcmanfm และ exit (ด้วย setid เทอร์มินัลสามารถปิดในขณะที่ pcmanfm ทำงานต่อไป) ขอบคุณมาก!
desgua

9

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

คุณอาจพิจารณาเริ่มต้นด้วย หน้าจอสามารถติดตั้งได้กับอนุพันธ์ของ Linux และ Unix เกือบทั้งหมด กดปุ่ม+ และ (ตัวพิมพ์เล็ก) จะเริ่มเซสชันที่สอง นี้จะช่วยให้คุณสามารถสลับไปมาระหว่างเซสชั่นเริ่มต้นโดยการกดปุ่ม+ และหรือเซสชั่นใหม่โดยการกดปุ่ม+ และ คุณสามารถมีได้มากถึงสิบเซสชันในหนึ่งเทอร์มินัล ผมใช้ในการเริ่มต้นเซสชั่นที่ทำงานกลับบ้าน SSH เข้าไปในเครื่องการทำงานของฉันแล้วเรียก นี่จะเชื่อมต่อคุณกับเซสชันระยะไกลอีกครั้งscreen -S session_nameCtrlACCtrlA0CtrlA1screen -d -R session_name


screen -d -m commandจะเริ่มภายในหน้าจอที่แยกออกแล้ว: ~# screen -d -m top ~# screen -ls There is a screen on: 10803..Server-station (Detached) 1 Socket in /root/.screen. ~# screen -x .... และคุณอยู่ในนั้น
ดร. อเล็กซานเดอร์

7

วิธีเชลล์เท่านั้นที่จะทำทั้งหมดนี้คือการปิด stdin และพื้นหลังคำสั่ง:

command <&- & 

จากนั้นมันจะไม่หยุดทำงานเมื่อคุณออกจากเชลล์ การเปลี่ยนเส้นทาง stdout เป็นอีกทางเลือกที่น่าสนใจ

ข้อเสียคือคุณไม่สามารถทำสิ่งนี้ได้หลังจากข้อเท็จจริง


ฉันลองในอูบุนตู สถานีฆ่าก็ปิดกระบวนการที่เปิดตัว มีความคิดเกี่ยวกับสาเหตุที่อาจเป็นเช่นนั้นหรือไม่?
Ashok Koyi

7

ฉันมีสคริปต์ไปที่:

  • เรียกใช้คำสั่งโดยพลการในพื้นหลัง

  • หยุดพวกเขาจากการถูกฆ่าด้วยหน้าต่างเทอร์มินัล

  • ปราบปรามการส่งออกของพวกเขา

  • จัดการสถานะทางออก

ฉันจะใช้มันเป็นหลักสำหรับgedit, evince, inkscapeฯลฯ ที่ทุกคนมีจำนวนมากของการส่งออกขั้วที่น่ารำคาญ หากคำสั่งเสร็จสิ้นก่อนหน้าTIMEOUTนี้สถานะการออกของ nohup จะถูกส่งคืนแทนที่จะเป็นศูนย์

#!/bin/bash

TIMEOUT=0.1

#use nohup to run the command, suppressing its output and allowing the terminal to be closed
#also send nohup's output to /dev/null, supressing nohup.out
#run nohup in the background so this script doesn't block
nohup "${@}" >/dev/null 2>&1 &
NOHUP_PID=$!

#kill this script after a short time, exiting with success status - command is still running
#this is needed as there is no timeout argument for `wait` below
MY_PID=$$
trap "exit 0" SIGINT SIGTERM
sleep $TIMEOUT && kill $MY_PID 2>/dev/null & #ignore "No such process" error if this exits normally

#if the command finishes before the above timeout, everything may be just fine or there could have been an error
wait $NOHUP_PID
NOHUP_STATUS=$?
#print an error if there was any. most commonly, there was a typo in the command
[ $NOHUP_STATUS != 0 ] && echo "Error ${@}"
#return the exit status of nohup, whatever it was
exit $NOHUP_STATUS

ตัวอย่าง...

>>> run true && echo success || echo fail
success
>>> run false && echo success || echo fail
Error false
fail
>>> run sleep 1000 && echo success || echo fail
success
>>> run notfound && echo success || echo fail
Error notfound
fail

6

ฉันชอบ:

(ชื่อแอปพลิเคชัน &)

ตัวอย่างเช่น: linux@linux-desktop:~$ (chromium-browser &)

ตรวจสอบให้แน่ใจว่าใช้วงเล็บเมื่อพิมพ์คำสั่ง!


1
การปิดเทอร์มินัลจะฆ่ากระบวนการซึ่งสิ่งที่ OP (และฉันดังนั้นมาที่นี่) ต้องการที่จะหลีกเลี่ยง
gromit190

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

ทำงานให้ฉันที
noadev

ฉันสงสัยว่าทำไมสิ่งนี้ถึงไม่เพิ่มขึ้น nohupป้องกันการส่งออก tty ใด ๆ และฉันแค่ต้องการเปลี่ยนเส้นทางการส่งออกไปยังไฟล์และป้องกันได้ดังนั้นนี่คือทางออกที่ดีกว่าสำหรับฉัน
redanimalwar

4

คุณสามารถตั้งค่ากระบวนการ (PID) ให้ไม่รับสัญญาณ HUP เมื่อออกจากระบบและปิดเซสชันเทอร์มินัล ใช้คำสั่งต่อไปนี้:

nohup -p PID

3

เนื้อหาที่คล้ายกับคำตอบที่เสนอโดย apolinskyฉันใช้ตัวแปรในscreenผมใช้เป็นตัวแปรในคำสั่งวานิลลาเป็นเช่นนี้

screen bash -c 'long_running_command_here; echo; read -p "ALL DONE:"'

เซสชั่นสามารถเชื่อมต่อกับและเชื่อมต่อในกรณีที่เรียบง่ายด้วยCtrl ACtrl D screen -rฉันได้นี้ห่อในสคริปต์ที่เรียกว่าsessionที่อาศัยอยู่ในของฉันPATHพร้อมสำหรับการเข้าถึงที่สะดวก:

#!/bin/bash
#
if screen -ls | awk '$1 ~ /^[1-9][0-9]*\.'"$1"'/' >/dev/null
then
    echo "WARNING: session is already running (reattach with 'screen -r $1')" >&2
else
    exec screen -S "$1" bash -c "$@; echo; echo '--------------------'; read -p 'ALL DONE (Enter to exit):'"
    echo "ERROR: 'screen' is not installed on this system" >&2
fi
exit 1

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


2

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

  1. หยุดกระบวนการชั่วคราว
  2. ดำเนินการกระบวนการต่อในพื้นหลัง
  3. ปฏิเสธกระบวนการ
  4. เปิดเซสชันหน้าจอ
  5. ค้นหา PID ของกระบวนการ
  6. ใช้ reptyr เพื่อทำตามกระบวนการ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.