it-swarm-vi.com

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?

Đô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?

339
Matthew

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

342
Steven D

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

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

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 quá trình kate tách ra khỏi konsole khi bạn chấm dứt konsole, hãy sử dụng Nohup bằng lệnh này, như sau:

Nohup kate &

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

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

kate sẽ tồn tại. :)

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

50
gertvdijk

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

31
hanoo

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ể cân nhắc bắt đầu với screen -S session_name. 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 Ctrl+A và (viết thường) C sẽ bắt đầu một 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 Ctrl+A và  hoặc phiên mới hơn bằng cách nhấn Ctrl+A và 1. Bạn có thể có tối đa mười phiên trong một thiết bị đầu cuối. Tôi đã từ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 mình và sau đó gọi screen -d -R session_name. Điều này sẽ kết nối bạn với phiên từ xa đó.

10
apolinsky

Tôi thích:

(Tên ứng dụng và)

ví dụ: [email protected]:~$ (chromium-browser &)

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

8
daGo

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 cho gedit, evince, inkscape vv mà tất cả đều có rất nhiều đầu ra khó chị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
7
jozxyqk

Cách duy nhất của Shell để làm 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 Shell. Chuyển hướng stdout là một điều tùy chọn tốt đẹp để làm.

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

7
w00t

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

Có thể tương tự như câu trả lời được cung cấp bởi 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ể bị ngắt kết nối với Ctrl ACtrl D và kết nối lại trong trường hợp đơn giản với screen -r. Tôi có gói này trong tập lệnh có tên session sống trong PATH sẵn sàng để 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 "[email protected]; 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.

3
roaima

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 này bài . 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 quản quá trình
2
user308879