Làm cách nào để tách toàn bộ quá trình khỏi Terminal?


304

Tôi sử dụng Tilda (thiết bị đầu cuối thả xuống) trên Ubuntu làm "trung tâm chỉ huy" của mình - gần như cách người khác có thể sử dụng Gnome Do, Quicksilver hoặc Launchy.

Tuy nhiên, tôi đang vật lộn với cách tách hoàn toàn một quy trình (ví dụ Firefox) khỏi thiết bị đầu cuối mà nó được khởi chạy từ - tức là ngăn chặn quá trình đó (không phải)

  • bị chấm dứt khi đóng thiết bị đầu cuối khởi tạo
  • "gây ô nhiễm" thiết bị đầu cuối khởi tạo thông qua STDOUT / STDERR

Ví dụ: để khởi động Vim trong cửa sổ đầu cuối "phù hợp", tôi đã thử một tập lệnh đơn giản như sau:

exec gnome-terminal -e "vim $@" &> /dev/null &

Tuy nhiên, điều đó vẫn gây ra ô nhiễm (đồng thời, việc chuyển một tên tệp dường như không hoạt động).


1
Đó cũng là một câu hỏi hay. Tôi nghĩ thật công bằng khi coi Bash là ngôn ngữ lập trình - mặc dù thực sự phạm vi của câu hỏi này có lẽ nhiều hơn ở phía sysadmin ...

Đây là bản sao của câu hỏi stackoverflow.com/questions/285015/ này
Dana the Sane


Trường hợp sử dụng của bạn không mô tả tách ra hoàn toàn, mỗi se.
jiggunjer

Câu trả lời:


344

Đầu tiên; một khi bạn đã bắt đầu một quá trình, bạn có thể nền nó bằng cách trước tiên dừng nó (nhấn Ctrl- Z) và sau đó gõ bgđể cho nó tiếp tục trong nền. Bây giờ nó là một "công việc" và stdout/ stderr/ stdinvẫn được kết nối với thiết bị đầu cuối của bạn.

Bạn có thể bắt đầu một quy trình làm nền ngay lập tức bằng cách thêm "&" vào cuối của nó:

firefox &

Để chạy nó trong nền im lặng, sử dụng:

firefox </dev/null &>/dev/null &

Một số thông tin bổ sung:

nohuplà một chương trình bạn có thể sử dụng để chạy ứng dụng của mình sao cho thiết bị xuất chuẩn / stderr của nó có thể được gửi đến một tệp thay vào đó và việc đóng tập lệnh gốc sẽ không SIGHUP cho trẻ. Tuy nhiên, bạn cần có tầm nhìn xa để sử dụng nó trước khi bạn khởi động ứng dụng. Do cách thức nohuphoạt động, bạn không thể chỉ áp dụng nó cho một quy trình đang chạy .

disownlà một bash dựng sẵn để loại bỏ một công việc shell khỏi danh sách công việc của shell. Điều này về cơ bản có nghĩa là bạn không thể sử dụng fg, bgtrên đó nữa, nhưng quan trọng hơn, khi bạn đóng vỏ của mình, nó sẽ không bị treo hoặc gửi SIGHUPcho đứa trẻ đó nữa. Không giống như nohup, disownđược sử dụng sau khi quá trình đã được đưa ra và nền.

Những gì bạn không thể làm, là thay đổi thiết bị xuất chuẩn / stderr / stdin của một quy trình sau khi đã khởi chạy nó. Ít nhất không phải từ vỏ. Nếu bạn khởi chạy tiến trình của mình và nói với nó rằng thiết bị xuất chuẩn của nó là thiết bị đầu cuối của bạn (đó là những gì bạn làm theo mặc định), thì quá trình đó được cấu hình để xuất ra thiết bị đầu cuối của bạn. Shell của bạn không có tác dụng với thiết lập FD của các quy trình, đó hoàn toàn là thứ mà chính quy trình đó quản lý. Quá trình tự nó có thể quyết định có đóng stdout / stderr / stdin của nó hay không, nhưng bạn không thể sử dụng trình bao của mình để buộc nó làm như vậy.

Để quản lý đầu ra của quy trình nền, bạn có rất nhiều tùy chọn từ các tập lệnh, "nohup" có lẽ là người đầu tiên nghĩ đến. Nhưng đối với các quá trình tương tác, bạn bắt đầu nhưng quên im lặng ( firefox < /dev/null &>/dev/null &) bạn thực sự không thể làm được gì nhiều.

Tôi khuyên bạn nên lấy GNU screen. Với màn hình, bạn chỉ có thể đóng vỏ đang chạy khi đầu ra của quá trình trở nên phiền phức và mở một cái mới ( ^Ac).


Ồ, và nhân tiện, đừng sử dụng " $@" nơi bạn đang sử dụng nó.

$@có nghĩa là, $1, $2, $3..., mà sẽ chuyển lệnh của bạn vào:

gnome-terminal -e "vim $1" "$2" "$3" ...

Đó có lẽ không phải là điều bạn muốn bởi vì - chỉ cần một đối số. Sử dụng $1để chỉ ra rằng tập lệnh của bạn chỉ có thể xử lý một đối số.

Thật sự rất khó để có nhiều đối số hoạt động chính xác trong kịch bản mà bạn đã đưa ra (với gnome-terminal -e) vì -echỉ lấy một đối số, đó là một chuỗi lệnh shell. Bạn sẽ phải mã hóa các đối số của mình thành một. Cách tốt nhất và mạnh mẽ nhất, nhưng khá vụng về, là như vậy:

gnome-terminal -e "vim $(printf "%q " "$@")"

Cảm ơn rất nhiều vì chuyện này! Đáng buồn là tôi chỉ có thể chấp nhận một câu trả lời. Tôi đã kết thúc với "nohup $ @ &> / dev / null &" và "alias wvim = 'launch.sh gnome-terminal -x vim'"

20
Thật là một câu trả lời chi tiết và nhiều thông tin. +1
Teekin

1
@ Hi-Angel khi bạn đóng một bash shell tương tác, bash HUP tất cả các công việc đang hoạt động. Khi bạn ^ Z và bg một quy trình, nó vẫn là một công việc, có thể là một nền tảng. Để loại bỏ nó như một công việc, sử dụng disown, sau đó quá trình sẽ tiếp tục sống sau khi bạn đóng vỏ vì bash sẽ không HUP nó nữa.
lhunath

3
Không sử dụng $*thay vì $@khắc phục sự cố của các chuỗi riêng biệt?
sjas

2
Những gì bạn không thể làm, là thay đổi thiết bị xuất chuẩn / stderr / stdin của một quy trình sau khi đã khởi chạy nó. - không chính xác Sử dụng reptyrcho việc này.
Stefan Seidel

198
nohup cmd &

nohup tách hoàn toàn quá trình (daemonizing nó)


5
Mặc dù cô đọng là có giá trị, sự đầy đủ có giá trị hơn. Mặc dù nohup là một lõi GNU, nhưng câu trả lời chỉ bash (hoặc lưu ý về việc không có ai) sẽ phù hợp ở đây. Câu trả lời tốt dù sao.
Chuộc tội có giới hạn

23
nohupchỉ cần bỏ qua SIGHUPtín hiệu. Nó thực hiện quá trình bình thường. Không daemonization.
nemo

1
@nemo Điều đó có nghĩa là quá trình không bị tách ra, nhưng sẽ bị tách ra (và là một đứa trẻ init) nếu vỏ thoát ra ... đúng không?
Noldorin

@Noldorin Có. Bỏ qua SIGHUP, được gửi khi shell kết thúc, sẽ khiến tiến trình con chạy và được chuyển sang init.
nemo

@nemo nohup cũng im lặng tiêu chuẩn vào / ra. Theo dõi với disown để hoàn toàn tách ra.
jiggunjer

60

Nếu bạn đang sử dụng bash, hãy thử ; xem bash (1) .disown [jobspec]

Một cách tiếp cận khác bạn có thể thử là at now. Nếu bạn không phải là siêu người dùng, quyền sử dụng của bạn atcó thể bị hạn chế.


"disown" dường như không phải là lệnh bash nội bộ (không khả dụng trên máy của tôi và tôi sử dụng bash). "Nohup", như Ben đề xuất, có thể là một cách tốt hơn (và tiêu chuẩn) để làm điều này.

1
không bao giờ nghĩ đến việc sử dụng "tại", cảm ơn vì ý tưởng!
cadrian

1
atđể ủy thác thực hiện cho người khác, tôi thích nó! +1
Ninsuo

1
Như một điểm tham chiếu, điều này cũng hoạt động zsh.
Bộ giải mã

1
Ngoài ra, disowndường như không có hiệu ứng mong muốn với các quy trình gnome-terminal- disowned vẫn bị giết khi thiết bị đầu cuối thoát. Tôi muốn biết tại sao / làm thế nào.
Kyle Strand

38

Đọc những câu trả lời này, tôi có ấn tượng ban đầu rằng việc ban hành nohup <command> &sẽ là đủ. Chạy zsh trong gnome-terminal, tôi thấy rằng điều đó nohup <command> &không ngăn được lớp vỏ của tôi giết chết các tiến trình con khi thoát. Mặc dù nohuprất hữu ích, đặc biệt là với các shell không tương tác, nó chỉ đảm bảo hành vi này nếu tiến trình con không thiết lập lại trình xử lý của nó cho SIGHUPtín hiệu.

Trong trường hợp của tôi, nohuplẽ ra đã ngăn các tín hiệu gác máy tiếp cận ứng dụng, nhưng ứng dụng con (VMWare Player trong trường hợp này) đã đặt lại SIGHUPtrình xử lý của nó . Kết quả là khi trình giả lập thiết bị đầu cuối thoát ra, nó vẫn có thể giết chết các quy trình con của bạn. Điều này chỉ có thể được giải quyết, theo hiểu biết của tôi, bằng cách đảm bảo rằng quy trình được xóa khỏi bảng công việc của trình bao. Nếu nohupđược ghi đè bằng một vỏ dựng sẵn, như đôi khi, trường hợp này có thể là đủ, tuy nhiên, trong trường hợp nó không ...


disownlà một vỏ BUILTIN trong bash, zshksh93,

<command> &
disown

hoặc là

<command> &; disown

nếu bạn thích một lớp lót. Điều này có tác dụng thường được mong muốn là loại bỏ tiến trình con khỏi bảng công việc. Điều này cho phép bạn thoát khỏi trình giả lập thiết bị đầu cuối mà không vô tình báo hiệu quá trình con. Cho dù người SIGHUPxử lý trông như thế nào, điều này không nên giết quá trình con của bạn.

Sau khi từ chối, quy trình vẫn là con của trình giả lập thiết bị đầu cuối của bạn (chơi với pstreenếu bạn muốn xem hoạt động này), nhưng sau khi trình giả lập thiết bị đầu cuối thoát, bạn sẽ thấy nó được gắn vào quy trình init. Nói cách khác, mọi thứ đều như vậy, và có lẽ bạn muốn nó như vậy.

Phải làm gì nếu vỏ của bạn không hỗ trợ disown? Tôi rất muốn ủng hộ việc chuyển sang một cái mà không, nhưng trong trường hợp không có tùy chọn đó, bạn có một vài lựa chọn.

  1. screentmuxcó thể giải quyết vấn đề này, nhưng chúng là giải pháp trọng lượng nặng hơn nhiều, và tôi không thích phải chạy chúng cho một nhiệm vụ đơn giản như vậy. Chúng phù hợp hơn nhiều cho các tình huống mà bạn muốn duy trì một tty, thường là trên một máy từ xa.
  2. Đối với nhiều người dùng, có thể mong muốn xem trình bao của bạn có hỗ trợ khả năng như zsh không setopt nohup. Điều này có thể được sử dụng để xác định rằng SIGHUPkhông nên gửi đến các công việc trong bảng công việc khi thoát khỏi trình bao. Bạn có thể áp dụng điều này ngay trước khi thoát khỏi shell hoặc thêm nó vào cấu hình shell như ~/.zshrcnếu bạn luôn muốn nó vào.
  3. Tìm cách chỉnh sửa bảng công việc. Tôi không thể tìm ra cách để làm điều này trong tcshhoặc csh, điều này hơi đáng lo ngại.
  4. Viết một chương trình C nhỏ để rẽ nhánh và exec(). Đây là một giải pháp rất kém, nhưng nguồn chỉ nên bao gồm vài chục dòng. Sau đó, bạn có thể truyền các lệnh dưới dạng đối số dòng lệnh cho chương trình C và do đó tránh được một mục cụ thể của quy trình trong bảng công việc.

29
  1. nohup $COMMAND &
  2. $COMMAND & disown
  3. setsid command

Tôi đã sử dụng số 2 trong một thời gian rất dài, nhưng số 3 cũng hoạt động tốt. Ngoài ra, disowncó một nohupcờ -h, có thể từ chối tất cả các quy trình -avà có thể từ chối tất cả các quy trình đang chạy với -ar.

Im lặng được thực hiện bởi $COMMAND &>/dev/null.

Hi vọng điêu nay co ich!


Ngắn và ngọt; cảm ơn vì tóm tắt rất hữu ích này
Sheljohn

Tôi không thể tin rằng tôi vẫn nhận được thông báo cho bài đăng này ...
Ông Minty Fresh

9

Tôi nghĩ màn hình có thể giải quyết vấn đề của bạn


9

trong tcsh (và có thể trong các shell khác), bạn có thể sử dụng dấu ngoặc đơn để tách quá trình.

So sánh điều này:

> jobs # shows nothing
> firefox &
> jobs
[1]  + Running                       firefox

Về điều này:

> jobs # shows nothing
> (firefox &)
> jobs # still shows nothing
>

Điều này loại bỏ firefox khỏi danh sách công việc, nhưng nó vẫn được gắn với thiết bị đầu cuối; nếu bạn đã đăng nhập vào nút này thông qua 'ssh', cố gắng đăng xuất vẫn sẽ treo quy trình ssh.


9

Câu trả lời đơn giản nhất và duy nhất cho bash:

command & disown

Bạn không phải tách quá trình từ thiết bị đầu cuối, nhưng từ vỏ.


7

Để phân tách lệnh tty shell run thông qua shell phụ, vd

(chỉ huy)&

Khi lối ra sử dụng thiết bị đầu cuối đóng nhưng quá trình vẫn còn sống.

kiểm tra -

(sleep 100) & exit

Mở thiết bị đầu cuối khác

ps aux | grep sleep

Quá trình vẫn còn sống.


Đây chính xác là những gì tôi cần. Tôi đã cố gắng thêm một lối tắt bàn điều khiển cho văn bản siêu phàm và nó hoạt động hoàn hảo, đây là những gì tôi đã kết thúc với: ("/ opt / Sublime Text 2 / sublime lòng" $ @) &
Ron E

5

Bối cảnh và tiền cảnh một công việc có lẽ là một trong những điều đầu tiên mà mọi quản trị viên hệ thống Unix nên biết.

Đây là cách nó được thực hiện với bash:

./script.sh
# suspend process
{ctrl-Z}
# background process
bg
# list all backgrounded jobs
jobs
# bring it back to foreground
fg

4

Bạn có thể chạy lệnh của mình bằng lệnh nohup, điều này tách quá trình của bạn và chuyển hướng đầu ra đến một tệp đã cho ... nhưng tôi không chắc đó là chính xác những gì bạn cần ..


Tôi có thể thề rằng tôi đã thử nohup trước khi sử dụng exec - nhưng dường như không đúng, vì nó hoạt động như thế này: nohup gnome-terminal -e "vim $ @" &> / dev / null &

2

Hãy thử daemon - nên có sẵn từ người quản lý gói thân thiện của bạn và chăm sóc toàn diện mọi cách tách rời khỏi thiết bị đầu cuối.


2

Chỉ cần thêm phần này vào bashrc / zshrc của bạn:

detach() {
  "$@" 1>/dev/null 2>/dev/null &; disown
}

Sau đó, bạn có thể chạy các lệnh bị từ chối như thế này:

detach gedit ~/.zshrc

1

Trong .bashrc của tôi, tôi có các hàm này cho mục đích chính xác đó:

function run_disowned() {
    "$@" & disown
}

function dos() {
    # run_disowned and silenced

    run_disowned "$@" 1>/dev/null 2>/dev/null
}

Tiền tố một lệnh dosđể chạy nó tách ra khỏi thiết bị đầu cuối.

Các chức năng được viết để làm việc với bashzsh.


1
Tôi hơi bối rối về lý do tại sao câu trả lời này sử dụng một chức năng được bọc vào một chức năng khác, khi nó chỉ đủ để sử dụng một chức năng với cơ thể như thế này : ( "$@" & disown) &> /dev/null. Nó cũng không có ý nghĩa nhiều khi sử dụng 1>2>, bởi vì bạn đang sử dụng disown, điều đó có nghĩa là bạn đang sử dụng bash, và trong bash, bạn có thể dễ dàng thực hiện &>để chuyển hướng cả stdout và stderr
Sergiy Kolodyazhnyy

Tôi có hai chức năng này bởi vì (1) Tôi nghĩ việc đọc theo cách này dễ dàng hơn và (2) Tôi cần run_disownedchức năng ở những nơi khác trong dotfiles của mình. Bạn đúng về &>điều này, tất nhiên.
mic_e

0

Tôi đã tìm thấy trên Mac OS X rằng tôi cần sử dụng cả nohup AND disown để đảm bảo rằng tiến trình con không bị phá hỏng với thiết bị đầu cuối.


0

Tôi sử dụng kịch bản sau đây để làm điều này. Nó dừng quá trình in tới thiết bị đầu cuối, tách ra nohupvà thoát với trạng thái trả về nếu lệnh kết thúc trong TIMEOUT.

#!/bin/bash

TIMEOUT=0.1

CMD=( "$@" )
#Could have some shortcuts here, e.g. replace "somefile.c" with "gedit somefile.c"

#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
#print the command for debugging and to see bash variable expansion
printf "%q " "${CMD[@]}"
echo
nohup "${CMD[@]}" >/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: $CMD"
#return the exit status of nohup, whatever it was
exit $NOHUP_STATUS

Ví dụ sử dụng:

>>> run false
false
Error: false
>>> echo $?
1
>>> run true
true
>>> run sleep 10
sleep 10
>>>

0

sudo apt install ucommon-utils

pdetach command

Bạn đi đây :)


-1

Nhiều câu trả lời đề nghị sử dụng nohup . Tôi muốn đề nghị sử dụng pm2 . Sử dụng pm2 trên nohup có nhiều lợi thế, như giữ cho ứng dụng tồn tại, duy trì các tệp nhật ký cho ứng dụng và nhiều tính năng khác. Để biết thêm chi tiết kiểm tra này .

Để cài đặt pm2 bạn cần tải xuống npm . Dành cho hệ thống dựa trên Debian

sudo apt-get install npm

và cho Redhat

sudo yum install npm

Hoặc bạn có thể làm theo các hướng dẫn này . Sau khi cài đặt npm, hãy sử dụng nó để cài đặt pm2

npm install pm2@latest -g

Sau khi hoàn thành, bạn có thể bắt đầu ứng dụng của mình bằng cách

$ pm2 start app.js              # Start, Daemonize and auto-restart application (Node)
$ pm2 start app.py              # Start, Daemonize and auto-restart application (Python)

Để giám sát quá trình sử dụng các lệnh sau:

$ pm2 list                      # List all processes started with PM2
$ pm2 monit                     # Display memory and cpu usage of each app
$ pm2 show [app-name]           # Show all informations about application

Quản lý các quy trình bằng tên ứng dụng hoặc id tiến trình hoặc quản lý tất cả các quy trình cùng nhau:

$ pm2 stop     <app_name|id|'all'|json_conf>
$ pm2 restart  <app_name|id|'all'|json_conf>
$ pm2 delete   <app_name|id|'all'|json_conf>

Các tệp nhật ký có thể được tìm thấy trong

$HOME/.pm2/logs #contain all applications logs

1
Sử dụng một ứng dụng NodeJS (so với một lệnh nhỏ và mạnh mẽ như nohup) để kiểm soát các quá trình unix dường như ... thực sự quá mức, và thành thật mà nói, khá kỳ lạ. Tôi sẽ sử dụng monit nếu bạn cần chức năng khởi động lại.
Sergio

@Sergio đó là sự lựa chọn của bạn để sử dụng ứng dụng bị lỗi thời.
haccks

Một số bản phát hành đã được thực hiện trong năm nay (một 4 ngày trước), vì vậy tôi không thấy làm thế nào / tại sao bạn có thể nghĩ rằng monit là một ứng dụng không dùng nữa. @see mmonit.com/monit/changes
Sergio

Tôi đã nói về nohup.
haccks

1
nohuplà một lệnh POSIX tiêu chuẩn đơn giản, vì vậy cùng một nhận xét: không có cách nào nó bị phản đối. @see unix.com/man-page/poseix/1p/nohup
Sergio

-1

Nếu mục tiêu của bạn chỉ đơn giản là khởi chạy một ứng dụng dòng lệnh mà không giữ cửa sổ terminal xung quanh, thì bạn có thể thử chạy ứng dụng sau khi khởi chạy terminal với alt-F2.

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.