Sự khác biệt giữa nohup, disown và &


579

Sự khác biệt giữa

$ nohup foo

$ foo &

$ foo & 
$ disown

50
Đợi đã, bạn có thể từ chối mà không chỉ định một PID? Tuyệt quá!
ripper234

34
Cũng foo &!có thể bằng với việc từ chối nó ngay từ đầu.
dùng4514

26
Bash không hỗ trợ &!.
Jonas Kongslund

20
foo & disownđể từ chối ngay lập tức.
ctrl-alt-delor

9
Tôi rất muốn thấy một đề cập đến setsid, và nó liên quan đến disownnohup
YoungFrog

Câu trả lời:


558

Trước tiên chúng ta hãy xem điều gì xảy ra nếu một chương trình được bắt đầu từ một vỏ tương tác (được kết nối với một thiết bị đầu cuối) mà không có &(và không có bất kỳ sự chuyển hướng nào). Vì vậy, giả sử bạn vừa gõ foo:

  • Quá trình chạy foođược tạo ra.
  • Quá trình kế thừa stdin, stdout và stderr từ shell. Do đó, nó cũng được kết nối với cùng một thiết bị đầu cuối.
  • Nếu shell nhận được a SIGHUP, nó cũng sẽ gửi a SIGHUPđến tiến trình (điều này thường làm cho quá trình kết thúc).
  • Nếu không, vỏ chờ (bị chặn) cho đến khi quá trình kết thúc.

Bây giờ, hãy xem điều gì sẽ xảy ra nếu bạn đặt quá trình ở chế độ nền, nghĩa là, gõ foo &:

  • Quá trình chạy foođược tạo ra.
  • Quá trình kế thừa stdout / stderr từ shell (vì vậy nó vẫn ghi vào terminal).
  • Quá trình về nguyên tắc cũng kế thừa stdin, nhưng ngay khi nó cố đọc từ stdin, nó đã bị dừng lại.
  • Nó được đưa vào danh sách các công việc nền mà shell quản lý, có nghĩa là đặc biệt:
    • Nó được liệt kê với jobsvà có thể được truy cập bằng cách sử dụng %n( nsố công việc ở đâu).
    • Nó có thể được chuyển thành một công việc tiền cảnh bằng cách sử dụng fg, trong trường hợp đó nó tiếp tục như thể bạn sẽ không sử dụng &nó (và nếu nó bị dừng do cố gắng đọc từ đầu vào tiêu chuẩn, bây giờ nó có thể tiến hành đọc từ thiết bị đầu cuối).
    • Nếu shell nhận được a SIGHUP, nó cũng sẽ gửi a SIGHUPtới tiến trình. Tùy thuộc vào trình bao và có thể tùy chọn được đặt cho trình bao, khi kết thúc trình bao, nó cũng sẽ gửi một SIGHUPquy trình.

Bây giờ disownloại bỏ công việc khỏi danh sách công việc của shell, vì vậy tất cả các điểm con ở trên không áp dụng nữa (bao gồm cả quá trình được gửi SIGHUPbởi shell). Tuy nhiên, lưu ý rằng nó vẫn được kết nối với thiết bị đầu cuối, vì vậy nếu thiết bị đầu cuối bị phá hủy (điều này có thể xảy ra nếu đó là một pty, giống như những thứ được tạo bởi xtermhoặc ssh, và chương trình điều khiển bị chấm dứt, bằng cách đóng xterm hoặc chấm dứt kết nối SSH ) , chương trình sẽ thất bại ngay khi nó cố đọc từ đầu vào tiêu chuẩn hoặc ghi vào đầu ra tiêu chuẩn.

nohupMặt khác, điều gì làm là tách hiệu quả quá trình khỏi thiết bị đầu cuối:

  • Nó đóng đầu vào tiêu chuẩn (chương trình sẽ không thể đọc bất kỳ đầu vào nào, ngay cả khi nó được chạy ở nền trước. Nó không bị dừng, nhưng sẽ nhận được mã lỗi hoặc EOF).
  • Nó chuyển hướng đầu ra tiêu chuẩn và lỗi tiêu chuẩn cho tập tin nohup.out, vì vậy chương trình sẽ không thể ghi vào đầu ra tiêu chuẩn nếu thiết bị đầu cuối bị lỗi, do đó, bất cứ điều gì quá trình ghi không bị mất.
  • Nó ngăn quá trình nhận một SIGHUP(vì vậy tên).

Lưu ý rằng nohupkhông phải loại bỏ quá trình này khỏi sự kiểm soát công việc của vỏ và cũng không đặt nó ở chế độ nền (nhưng vì một foreground nohupcông việc là nhiều hơn hoặc ít vô dụng, bạn sẽ thường đặt nó vào nền sử dụng &). Ví dụ, không giống như disown, shell vẫn sẽ cho bạn biết khi nào công việc nohup đã hoàn thành (tất nhiên trừ khi shell bị chấm dứt trước đó, tất nhiên).

Vì vậy, để tóm tắt:

  • & đặt công việc ở chế độ nền, nghĩa là làm cho nó bị chặn khi cố đọc đầu vào và làm cho trình bao không chờ hoàn thành.
  • disownloại bỏ quá trình khỏi kiểm soát công việc của shell, nhưng nó vẫn để nó kết nối với thiết bị đầu cuối. Một trong những kết quả là vỏ sẽ không gửi nó a SIGHUP. Rõ ràng, nó chỉ có thể được áp dụng cho các công việc nền, bởi vì bạn không thể nhập nó khi một công việc nền trước đang chạy.
  • nohupngắt kết nối tiến trình từ thiết bị đầu cuối, chuyển hướng đầu ra của nó đến nohup.outvà bảo vệ nó khỏi SIGHUP. Một trong những hiệu ứng (cách đặt tên) là quá trình sẽ không nhận được bất kỳ gửi nào SIGHUP. Nó hoàn toàn độc lập với kiểm soát công việc và về nguyên tắc có thể được sử dụng cho các công việc tiền cảnh (mặc dù điều đó không hữu ích lắm).

8
+1 Cảm ơn. Điều gì xảy ra khi sử dụng disown, nohup và & together?
Tim

15
Nếu bạn sử dụng cả ba cùng nhau, quy trình đang chạy trong nền, sẽ bị xóa khỏi kiểm soát công việc của trình bao và bị ngắt kết nối khỏi thiết bị đầu cuối một cách hiệu quả.
celtschk


1
sự khác biệt giữa disown %1disown -h %1? Công việc thứ hai sẽ giữ như một công việc thông thường (nhưng bỏ qua tín hiệu HUP) cho đến khi thoát khỏi thiết bị đầu cuối?
schemacs

4
Có thể có giá trị bao gồm cả (foo&)subshell
jiggunjer

169

Việc sử dụng &khiến chương trình chạy trong nền, vì vậy bạn sẽ nhận được lời nhắc shell mới thay vì chặn cho đến khi chương trình kết thúc. nohupdisownphần lớn không liên quan; chúng triệt tiêu tín hiệu SIGHUP (gác máy) để chương trình không tự động bị tắt khi thiết bị đầu cuối điều khiển bị đóng. nohuplàm điều này khi công việc đầu tiên bắt đầu. Nếu bạn không nohuplàm việc khi nó bắt đầu, bạn có thể sử dụng disownđể sửa đổi công việc đang chạy; không có đối số, nó sửa đổi công việc hiện tại, đó là công việc vừa được làm nền


10
Sự khác biệt nhỏ giữa nohup và disown: lệnh disown sẽ xóa nó khỏi danh sách công việc của bạn; nohup sẽ không.
Shawn J. Goff

191
nohupdisowncả hai có thể nói là đàn áp SIGHUP, nhưng theo những cách khác nhau. nohuplàm cho chương trình bỏ qua tín hiệu ban đầu (chương trình có thể thay đổi điều này). nohupcũng cố gắng sắp xếp để chương trình không có thiết bị đầu cuối điều khiển, để nó sẽ không được gửi SIGHUPbởi kernel khi thiết bị đầu cuối bị đóng. disownlà hoàn toàn nội bộ cho vỏ; nó làm cho vỏ không gửi được SIGHUPkhi nó kết thúc.
Gilles

27
@Gilles, bình luận của bạn đáng để trả lời.
lesmana

5
Chỉ cần làm rõ về nhận xét của @ ShawnJ.Goff liên quan đến disownviệc loại bỏ công việc khỏi danh sách công việc. Nếu bạn không chỉ định một tùy chọn, nó sẽ xóa nó khỏi danh sách công việc. Tuy nhiên , nếu bạn chỉ định -htùy chọn, mỗi jobspec sẽ không bị xóa khỏi bảng. Thay vào đó, nó làm cho nó SIGHUPkhông được gửi đến công việc nếu shell nhận được a SIGHUP.
tacotuesday

4
Chỉ cần làm rõ, việc sử dụng &không cung cấp cho bạn một thiết bị đầu cuối, nó tách ra stdinkhỏi quy trình và khiến nó chạy trong nền, nhưng cả hai stdoutstderrvẫn được gắn vào tty hiện tại. Điều này có nghĩa là bạn có thể nhận được văn bản từ các chương trình khác nhau được trộn lẫn với nhau, điều này có thể khá khó chịu nếu bạn làm gimp &và gặp nhiều lỗi GTK + trong khi cố gắng sử dụng tty đó cho mục đích khác.
Frank

8

Dưới đây là kinh nghiệm của tôi khi cố gắng chạy soffice trong nền, theo lệnh không kết thúc (ví dụ tail). Ví dụ này tôi sẽ sử dụng sleep 100.

&

#!/bin/bash
/opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

Tôi thấy nhật ký soffice / bằng cách nhấn Ctrl- Csoffice dừng

không .. &

#!/bin/bash
nohup /opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

Tôi không thấy nhật ký soffice / bằng cách nhấn Ctrl- Csoffice dừng

& từ chối

#!/bin/bash
/opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard & disown
sleep 100

Tôi thấy nhật ký soffice / bằng cách nhấn Ctrl- Csoffice dừng

setid .. &

#!/bin/bash
setsid /opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

Tôi thấy nhật ký soffice / bằng cách nhấn Ctrl- Csoffice KHÔNG DỪNG

Để tiết kiệm dung lượng ::
nohup setsid ..không hiển thị nhật ký / soffice KHÔNG DỪNG vào Ctrl-C
nohup với & disownở cuối: không hiển thị nhật ký / soffice dừng trên Ctrl-C


2
Trong khi tôi đánh giá cao nỗ lực đề cập đến setsid và cho thấy những gì xảy ra trong tình huống cụ thể đó, tôi muốn thấy một câu trả lời kỹ lưỡng hơn. Cụ thể, sự khác biệt và tương đồng của từng giải pháp, cả hai đều có thể nhìn thấy (điều xảy ra khi đóng vỏ hoặc thiết bị đầu cuối, đầu ra đi đâu, ...) và vô hình (cách mọi thứ được thực hiện dưới mui xe và ý nghĩa của chúng). Câu trả lời được chấp nhận là một cơ sở tốt đẹp cho điều đó.
YoungFrog

1
@YoungFrog Tôi sẽ đồng ý về điều này!
Marinos An

Đối với tôi, với nohup ⟨command⟩ & disownquá trình tạo ra không dừng lại Ctrl+C.
k.stm

@ k.stm Bạn đã thử sofficechưa? sofficelệnh dường như có một cái gì đó khác nhau. Vì vậy, tôi coi việc thêm nó ở đây là một ngoại lệ quy tắc. ví dụ: khi sử dụng : nohup .. &, nhấn Ctrl-cbình thường không làm cho lệnh dừng lại, nhưng với sofficenó thì không. Tôi đợi cho đến khi ai đó bước vào điều này và giải thích lý do tại sao điều này xảy ra với soffice :)
Marinos An

@MarinosAn Vâng, tôi đã làm. Tôi chạy nohup soffice &và ép Ctrl+C. Không có gì xảy ra, như mong đợi.
k.stm
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.