Làm thế nào tôi có thể chạy một lệnh sẽ tồn tại gần thiết bị đầu cuối?


313

Đôi khi tôi muốn bắt đầu một quá trình và quên nó đi. Nếu tôi bắt đầu nó từ dòng lệnh, như thế này:

redshift

Tôi không thể đóng thiết bị đầu cuối, hoặc nó sẽ giết quá trình. Tôi có thể chạy một lệnh theo cách mà tôi có thể đóng thiết bị đầu cuối mà không làm hỏng quá trình không?


4
Không phải cài đặt mặc định trên tất cả các bản phát hành, nhưng màn hình là bạn của bạn: en.wikipedia.org/wiki/GNU_Screen
Zayne S Halsall

Đối với bất kỳ ai gặp phải cùng một vấn đề: Hãy nhớ rằng, ngay cả khi bạn nhập yourExecutable &và các đầu ra tiếp tục xuất hiện trên màn hình và Ctrl+Cdường như không dừng lại bất cứ điều gì, chỉ cần gõ disown;và nhấn một cách mù quáng Enterngay cả khi màn hình đang cuộn với đầu ra và bạn không thể thấy gì bạn đang gõ Quá trình sẽ bị từ chối và bạn sẽ có thể đóng thiết bị đầu cuối mà không bị quá trình chết.
Nav

Bạn có thể sử dụng màn hình đa như tmux . Nó có sẵn thông qua apt-get trên các máy
ubfox

Câu trả lời:


311

Một trong 2 điều sau đây sẽ hoạt động:

$ nohup redshift &

hoặc là

$ redshift &
$ disown

Xem phần sau để biết thêm một chút thông tin về cách thức hoạt động của nó:


5
Cái thứ hai ( redshift & disown) làm việc cho tôi trên Ubuntu 10.10. Nó dường như hoạt động tốt khi đặt tất cả trên một dòng. Có bất kỳ lý do mà tôi không nên làm điều này?
Matthew

4
@Matthew Cái đầu tiên cũng hoạt động tốt, nó không giống như cái thứ hai (bạn có thể muốn nohup redshift &nó làm nền). Và đặt dòng thứ hai trên một dòng là tốt, mặc dù thông thường bạn tách riêng với ;( redshift &; disown)
Michael Mrozek

10
@Michael: Cả hai ;&là dấu phân cách lệnh và có quyền ưu tiên như nhau. Sự khác biệt duy nhất là thực thi đồng bộ so với không đồng bộ (tương ứng). Không cần sử dụng &;ưu tiên chỉ &(nó hoạt động, nhưng nó hơi dư thừa).
Chris Johnsen

4
câu trả lời hay, người ta có thể nói thêm rằng đó là một ý tưởng tốt để chuyển hướng thiết bị xuất chuẩn và thiết bị xuất chuẩn để thiết bị đầu cuối không bị spam với đầu ra gỡ lỗi
Kim

12
Ngoài ra, redshift &!sẽ từ chối dịch chuyển đỏ ngay lập tức.

143

Nếu chương trình của bạn đang chạy, bạn có thể tạm dừng chương trình đó Ctrl-Z, kéo nó vào nền bgvà sau disownđó, như thế này:

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

3
Sau khi từ chối, làm thế nào tôi có thể đọc lại thiết bị xuất chuẩn của quá trình đang chạy?
Necktwi


1
Điều này không làm việc cho tôi vì một số lý do (centos)
Ian

Làm thế nào để giết quá trình sau thủ tục này?
Palak Darji

2
@necktwi disownkhông ngắt kết nối thiết bị xuất chuẩn hoặc thiết bị xuất chuẩn. Tuy nhiên nohup, cũng như >/dev/null(ngắt kết nối ra tiêu chuẩn), 2>/dev/null(ngắt kết nối lỗi tiêu chuẩn). Nó ( disown) ngắt kết nối kiểm soát công việc.
ctrl-alt-delor

45

Câu trả lời tốt đã được đăng bởi @StevenD, nhưng tôi nghĩ điều này có thể làm rõ hơn một chút.

Lý do mà quá trình bị hủy khi chấm dứt thiết bị đầu cuối là vì quy trình bạn bắt đầu là một quy trình con của thiết bị đầu cuối. Khi bạn đóng thiết bị đầu cuối, điều này cũng sẽ giết các tiến trình con này. Bạn có thể thấy cây quy trình với pstree, ví dụ như khi chạy kate &trong Konsole:

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

Để làm cho katequá trình tách ra từ konsolekhi bạn chấm dứt konsole, hãy sử dụng nohupvới lệnh, như thế này:

nohup kate &

Sau khi đóng konsole, pstreesẽ như thế này:

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

katesẽ tồn tại. :)

Một thay thế là sử dụng screen/ tmux/ byobu, sẽ giữ cho vỏ chạy, độc lập với thiết bị đầu cuối.


Tôi đã có vấn đề với các phương pháp disown. Điều này hiện đang làm việc cho tôi, vì vậy nâng cao. Tôi cũng thích điều này bởi vì tôi có thể theo đuôi -f nohup.out để xem điều gì đang xảy ra, nhưng không lo lắng về phiên của tôi thất bại
Ian

27

Bạn có thể chạy quy trình như thế này trong thiết bị đầu cuối

setsid process

Điều này sẽ chạy chương trình trong một phiên mới. Như đã giải thích http://hanoo.org/index.php?article=run-program-in-new-session-linux


1
Bạn thấy lợi thế của setsid so với nohup là gì?
itbruce

1
1) Nó không in một thông điệp gây phiền nhiễu về nohup.out. 2) Nó không còn trong danh sách công việc của shell của bạn, vì vậy nó không làm lộn xộn đầu ra của jobs.
Mikel

Đây là giải pháp duy nhất hoạt động với tập lệnh chạy trong lxterminal, khởi chạy pcmanfm và thoát (với setsid, thiết bị đầu cuối có thể đóng trong khi pcmanfm tiếp tục chạy). Cảm ơn bạn rất nhiều!
desgua

9

Mặc dù tất cả các đề xuất đều hoạt động tốt, tôi đã tìm thấy giải pháp thay thế của mình là sử dụng screen, một chương trình thiết lập một thiết bị đầu cuối ảo trên màn hình của bạn.

Bạn có thể xem xét bắt đầu nó với . Màn hình có thể được cài đặt trên hầu như tất cả các dẫn xuất Linux và Unix. Đánh + và (chữ thường) sẽ bắt đầu phiên thứ hai. Điều này sẽ cho phép bạn chuyển đổi qua lại giữa phiên ban đầu bằng cách nhấn + và hoặc phiên mới hơn bằng cách nhấn + và . Bạn có thể có tối đa mười phiên trong một thiết bị đầu cuối. Tôi thường bắt đầu một phiên làm việc, về nhà, ssh vào máy làm việc của tôi và sau đó gọi . Điều này sẽ kết nối bạn với phiên từ xa đó.screen -S session_nameCtrlACCtrlA0CtrlA1screen -d -R session_name


screen -d -m commandsẽ khởi động nó trong màn hình đã tách ra: ~# screen -d -m top ~# screen -ls There is a screen on: 10803..Server-station (Detached) 1 Socket in /root/.screen. ~# screen -x .... và bạn đang ở.
Tiến sĩ Alexander

7

Cách duy nhất để thực hiện tất cả điều này là đóng stdin và làm nền cho lệnh:

command <&- & 

Sau đó, nó sẽ không thoát khi bạn thoát khỏi vỏ. Chuyển hướng stdout là một điều tốt đẹp tùy chọn để làm.

Nhược điểm là bạn không thể làm điều này sau khi thực tế.


Tôi đã thử trong Ubuntu. Thiết bị đầu cuối giết chết cũng đóng cửa quá trình khởi động. Bất cứ ý tưởng về lý do tại sao điều này có thể là trường hợp?
Ashok Koyi

7

Tôi có một kịch bản để:

  • Chạy các lệnh tùy ý trong nền

  • Ngăn chặn họ khỏi bị giết với cửa sổ thiết bị đầu cuối

  • Ức chế đầu ra của họ

  • Xử lý tình trạng thoát

Tôi sử dụng nó chủ yếu là cho gedit, evince, inkscapevv mà tất cả đều có rất nhiều đầu ra thiết bị đầu cuối gây phiền nhiễu. Nếu lệnh kết thúc trước đó TIMEOUT, trạng thái thoát của nohup được trả về thay vì 0.

#!/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

ví dụ ...

>>> 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

Tôi thích:

(tên ứng dụng &)

ví dụ: linux@linux-desktop:~$ (chromium-browser &)

Đảm bảo sử dụng dấu ngoặc đơn khi gõ lệnh!


1
Đóng thiết bị đầu cuối sẽ giết quá trình , đó chính xác là những gì OP (và tôi, do đó đến đây) muốn tránh
gromit190

Có lẽ bạn có lệnh nhanh chóng mà tôi đã sử dụng trong câu trả lời của mình mà không có dấu ngoặc đơn, nếu vậy việc đóng thiết bị đầu cuối sẽ giết quá trình, nếu không nó sẽ KHÔNG xảy ra. Tôi đã chỉnh sửa giải pháp ở trên để làm cho nó rõ ràng.
daGo

làm việc cho tôi, tnx
noadev

Tôi tự hỏi tại sao điều này không có nhiều upvote. nohupngăn chặn bất kỳ đầu ra tty nào và tôi thực sự chỉ muốn chuyển hướng đầu ra sang một tệp và nó đã ngăn chặn điều đó vì vậy đây là giải pháp tốt hơn cho tôi.
redanimalwar

4

Bạn có thể đặt quy trình (PID) để không nhận tín hiệu HUP khi đăng xuất và đóng phiên cuối. Sử dụng lệnh sau:

nohup -p PID

3

Tương tự như câu trả lời của apolinsky , tôi sử dụng một biến thể trên screen. Lệnh vanilla là như thế này

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

Phiên có thể được ngắt kết nối Ctrl ACtrl Dvà kết nối lại trong trường hợp đơn giản với screen -r. Tôi đã này được bọc trong một kịch bản gọi là sessionsống trong tôi PATHsẵn sàng cho việc truy cập thuận tiện:

#!/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

Điều này chỉ hoạt động khi bạn biết trước bạn muốn ngắt kết nối một chương trình. Nó không cung cấp cho một chương trình đang chạy bị ngắt kết nối.


2

Tương tự như các câu trả lời khác được đăng trước đó, người ta có thể chuyển một quy trình đang chạy để sử dụng "màn hình" hồi cứu nhờ reptyr và sau đó đóng thiết bị đầu cuối. Các bước được mô tả trong bài viết này . Các bước cần thực hiện là:

  1. Đình chỉ quá trình
  2. Tiếp tục quá trình trong nền
  3. Bỏ quy trình
  4. Khởi chạy một phiên màn hình
  5. Tìm PID của quá trình
  6. Sử dụng reptyr để tiếp nhận quá trình
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.