Câu hỏi Làm thế nào để tách một quá trình từ Terminal, hoàn toàn?


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 tôi - khá nhiều cách người khác có thể sử dụng GNOME Do, Quicksilver hoặc Launchy.

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

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

Ví dụ, để bắt đầu Vim trong một cửa sổ terminal "thích hợp", tôi đã thử một kịch bản đơ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 tin dường như không hoạt động).


274
2018-03-23 11:59


gốc


Đó cũng là một câu hỏi hay. Tôi nghĩ thật công bằng khi xem Bash một 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ẽ là nhiều hơn ở phía bên sysadmin ...
Đây là bản sao của câu hỏi này stackoverflow.com/questions/285015/… - Dana the Sane
dup của:superuser.com/questions/177218/… - behrooz
Trường hợp sử dụng của bạn không mô tả hoàn toàn tách rời, mỗi lần. - jiggunjer


Các câu trả lời:


Đầ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 đầu tiên dừng nó (nhấn Ctrl- -Z) và sau đó nhập bg để cho nó tiếp tục trong nền. Bây giờ nó là "công việc" và stdout/stderr/stdin vẫ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 quá trình làm nền ngay lập tức bằng cách gắn thêm "&" vào cuối:

firefox &

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

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

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

nohup là một chương trình bạn có thể sử dụng để chạy ứng dụng của bạn với sao cho stdout / 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 mẹ sẽ không SIGHUP con. Tuy nhiên, bạn cần phải có tầm nhìn xa đã sử dụng nó trước khi bạn bắt đầu ứng dụng. Vì đường nohup hoạt động, bạn không thể chỉ áp dụng nó cho một quá trình chạy.

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

Bạn là gì không thể làm, là thay đổi stdout / stderr / stdin của một quá trình sau khi đã khởi chạy nó. Ít nhất không phải từ vỏ. Nếu bạn khởi động quá trình của bạn và nói với nó rằng stdout của nó là terminal 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 terminal của bạn. Vỏ của bạn không có kinh doanh với các thiết lập FD của quy trình, đó hoàn toàn là một cái gì đó mà quá trình tự quản lý. Quá trình tự nó có thể quyết định có nên đóng stdout / stderr / stdin của nó hay không, nhưng bạn không thể sử dụng shell của bạn để buộc nó làm như vậy.

Để quản lý đầu ra của quá trình nền, bạn có rất nhiều tùy chọn từ tập lệnh, "nohup" có thể là thứ đầu tiên cần lưu ý. 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 không thể làm nhiều, thực sự.

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


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

$@có nghĩa, $1, $2, $3 ..., sẽ biến lệnh của bạn thành:

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

Đó có lẽ không phải những gì bạn muốn bởi vì - chỉ mất một tranh luận. Sử dụng $1 để cho thấy rằng tập lệnh của bạn chỉ có thể xử lý một đối số.

Rất khó để có được nhiều đối số hoạt động đúng trong kịch bản mà bạn đã đưa ra (với gnome-terminal -e) bởi vì -e chỉ nhận 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 bạn thành một. Cách tốt nhất và mạnh mẽ nhất, nhưng khá thô lỗ, giống như vậy:

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

308
2018-03-23 13:18



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 bằng "nohup $ @ &> / dev / null &" và "alias wvim = 'launch.sh gnome-terminal -x vim'"
Thật là một câu trả lời tuyệt vời và chi tiết. +1 - Teekin
@ Hi-Angel khi bạn đóng một vỏ bash 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 quá trình nó vẫn là một công việc, có thể nó là một nền tảng. Để xóa 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ỏ kể từ khi bash sẽ không HUP nó nữa. - lhunath
Sẽ không sử dụng $* thay vì $@ khắc phục sự cố của các chuỗi riêng biệt? - sjas
Những gì bạn không thể làm, là thay đổi stdout / stderr / stdin của một quá trình sau khi đã khởi chạy nó. - không chính xác. Sử dụng reptyr cho điều này. - Stefan Seidel


nohup cmd &

nohup detaches quá trình hoàn toàn (daemonizes nó)


190
2018-03-23 12:17



Mặc dù ngắn gọn là có giá trị, sự hoàn chỉnh có giá trị hơn. Mặc dù nohup là một coreutil GNU, một câu trả lời bash chỉ (hoặc lưu ý về không có một) sẽ là thích hợp ở đây. Tốt câu trả lời dù sao. - Limited Atonement
nohup chỉ bỏ qua SIGHUP tín hiệu. Nó thực hiện quá trình bình thường. Không có daemonization. - nemo
@nemo Có nghĩa là quá trình này không bị tách rời, nhưng sẽ bị tách rời (và con của init) nếu vỏ thoát ... phải không? - Noldorin
@Noldorin Có. Bỏ qua SIGHUP, được gửi khi shell kết thúc, sẽ rời khỏi tiến trình con đang chạy và được chuyển đến init. - nemo
@nemo nohup cũng im lặng tiêu chuẩn trong / outs. Theo dõi với disown để hoàn toàn tách ra. - jiggunjer


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

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à superuser, bạn được phép sử dụng at có thể bị hạn chế.


51
2018-03-23 12:05



"disown" dường như không phải là lệnh bash bên trong (không có sẵn trên máy của tôi và tôi sử dụng bash). "nohup", như Ben đề nghị, có thể là một cách tốt hơn (và tiêu chuẩn) để làm điều này.
không bao giờ nghĩ đến việc sử dụng "at", cảm ơn ý tưởng! - cadrian
at để ủy quyền thực hiện cho người khác, tôi thích nó! +1 - Ninsuo
Là một điểm tham chiếu, điều này hoạt động zsh cũng. - Coderer
Cũng thế, disown dường như không có hiệu quả mong muốn với gnome-terminal- -disowncác quy trình ed vẫn bị giết khi thiết bị đầu cuối thoát. Tôi rất muốn biết tại sao / như thế nào. - Kyle Strand


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

Trong trường hợp của tôi, nohup nên đã ngăn chặ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) đã được đặt lại SIGHUP xử lý. Kết quả là khi trình mô phỏng thiết bị đầu cuối thoát ra, nó vẫn có thể giết các tiến 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 quá trình được lấy ra khỏi bảng công việc của trình bao. Nếu nohup được ghi đè với một nội trang hệ vỏ, như đôi khi trường hợp, điều này có thể là đủ, tuy nhiên, trong trường hợp nó không phải là ...


disown là một nội trang hệ vỏ 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 mong muốn chung 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 mô phỏng thiết bị đầu cuối mà không vô tình báo hiệu quá trình con. Không có vấn đề gì SIGHUP xử lý trông giống như, điều này không nên giết quá trình con của bạn.

Sau khi bị xóa, quá trình này vẫn là một phần tử con của trình mô phỏng đầu cuối của bạn (chơi với pstree nếu bạn muốn xem điều này trong hành động), nhưng sau khi trình mô phỏng thiết bị đầu cuối thoát, bạn sẽ thấy nó được gắn vào quá trình init. Nói cách khác, tất cả mọi thứ là như nó phải được, và như bạn có lẽ muốn nó được.

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

  1. screen và tmux có thể giải quyết vấn đề này, nhưng chúng có nhiều giải pháp trọng lượng nặng hơn, 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 với 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 liệu trình bao của bạn có hỗ trợ khả năng như zsh hay không setopt nohup. Điều này có thể được sử dụng để chỉ định SIGHUPkhông được gửi đến các công việc trong bảng công việc khi trình bao thoát. 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ư ~/.zshrc nếu bạn luôn muốn.
  3. Tìm cách chỉnh sửa bảng công việc. Tôi không thể tìm cách để làm điều này trong tcsh hoặc là csh, có phần đáng lo ngại.
  4. Viết một chương trình C nhỏ để ngã ba và exec(). Đây là một giải pháp rất kém, nhưng nguồn chỉ nên bao gồm một vài chục dòng. Sau đó bạn có thể chuyển các lệnh như các đối số dòng lệnh tới chương trình C, và do đó tránh một mục nhập quy trình cụ thể trong bảng công việc.

34
2018-01-22 17:08





  1. nohup $ COMMAND &

  2. $ COMMAND & disown

  3. lệnh setid

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, disown có một 'nohup' flag của '-h', có thể disown tất cả các process với '-a', và có thể disown tất cả các tiến 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!


23
2017-08-25 14:39





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


9
2018-03-25 01:51





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

Để đ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òn 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 sẽ vẫn treo quá trình ssh.


8
2018-03-23 14:55





Để hủy liên kết lệnh chạy trình bao tty thông qua trình bao con cho ví dụ:

(chỉ huy)&

Khi thoát khỏi terminal đã sử dụng nhưng quá trình vẫn còn hoạt độ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.


6
2017-08-07 05:18



Đây chính xác là những gì tôi cần. Tôi đã cố thêm một lối tắt bàn điều khiển cho văn bản tuyệt vời 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_text" $ @) & - Ron E


Câu trả lời chính xác và đơn giản nhất cho bash:

command & disown

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


6
2018-05-05 11:55



Làm việc hoàn hảo. Cảm ơn bạn. - Royi


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


4
2018-03-23 12:03



Tôi có thể thề 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 &


Bối cảnh và làm nền trước 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 Unix cầ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
2018-05-22 23:00