Các quy trình nền có nhận được SIGHUP khi đăng xuất không?


21

Đây là một tiếp theo cho câu hỏi này .

Tôi đã chạy thêm một số bài kiểm tra; có vẻ như nó thực sự không quan trọng nếu điều này được thực hiện tại bảng điều khiển vật lý hoặc thông qua SSH, điều này cũng không xảy ra chỉ với SCP; Tôi cũng đã thử nó với cat /dev/zero > /dev/null. Hành vi hoàn toàn giống nhau:

  • Bắt đầu một quá trình trong nền bằng cách sử dụng &(hoặc đặt nó vào nền sau khi nó bắt đầu sử dụng CTRL-Zbg); Điều này được thực hiện mà không cần sử dụngnohup .
  • Đăng xuất.
  • Đăng nhập lại.
  • Quá trình vẫn còn đó, chạy một cách vui vẻ, và bây giờ là một đứa trẻ trực tiếp init.

Tôi có thể xác nhận cả SCP và CAT thoát ngay lập tức nếu được gửi a SIGHUP; Tôi đã thử nghiệm điều này bằng cách sử dụng kill -HUP.

Vì vậy, có vẻ như SIGHUP không được gửi khi đăng xuất, ít nhất là cho các quy trình nền (không thể kiểm tra với tiền cảnh vì lý do rõ ràng).

Điều này xảy ra với tôi ban đầu với bảng điều khiển dịch vụ của VMware ESX 3.5 (dựa trên RedHat), nhưng tôi đã có thể sao chép chính xác trên CentOS 5.4.

Một lần nữa, câu hỏi đặt ra là: SIGHUP có nên được gửi đến các quy trình hay không, ngay cả khi chúng đang chạy ẩn, khi đăng xuất? Tại sao điều này không xảy ra?


Chỉnh sửa

Tôi đã kiểm tra với stracecâu trả lời của Kyle.
Như tôi đã mong đợi, quá trình không nhận được bất kỳ tín hiệu nào khi đăng xuất khỏi vỏ nơi nó được khởi chạy. Điều này xảy ra cả khi sử dụng bảng điều khiển của máy chủ và qua SSH.


Sử dụng Bash trên CentOS 7.1, một vòng lặp shell shell đơn giản sẽ nhận được SIGHUP nếu nó bị bỏ lại phía trước, nhưng thiết bị đầu cuối bị giết; bước đi từ một nhà ga khác cho thấy: --- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=10676, si_uid=3000090} --- rt_sigreturn() = -1 EINTR (Interrupted system call) rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
Mike S

Vì vậy, một kịch bản nền. Lưu ý rằng thiết bị đầu cuối được đóng trong khi vòng lặp đang chờ ngủ. Vỏ KHÔNG được thoát:--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=13944, si_uid=3000090} --- +++ killed by SIGHUP +++
Mike S

Xem câu trả lời của tôi để kiểm tra. Thật thú vị, tôi thấy không có thay đổi trong hành vi do huponexit.
Mike S

Câu trả lời:


26

Trả lời tìm thấy.

Đối với BASH, điều này phụ thuộc vào huponexittùy chọn shell, có thể được xem và / hoặc thiết lập bằng cách sử dụng shoptlệnh tích hợp.

Có vẻ như các tùy chọn này được tắt theo mặc định, ít nhất là trên các hệ thống dựa trên RedHat.

Thông tin thêm trên trang người đàn ông BASH :

Shell thoát theo mặc định khi nhận được SIGHUP. Trước khi thoát, một vỏ tương tác gửi lại SIGHUP cho tất cả các công việc, đang chạy hoặc dừng. Các công việc đã dừng được gửi SIGCONT để đảm bảo rằng họ nhận được SIGHUP. Để ngăn vỏ gửi tín hiệu đến một công việc cụ thể, cần loại bỏ nó khỏi bảng công việc với phần dựng sẵn (xem SHELL BUILTIN THÔNG TIN bên dưới) hoặc được đánh dấu để không nhận SIGHUP bằng cách sử dụng từ chối -h.

Nếu tùy chọn shell huponexit đã được đặt với shopt, bash sẽ gửi SIGHUP cho tất cả các công việc khi thoát khỏi vỏ đăng nhập tương tác.


4
Đã xác minh. Khi tôi thực hiện "thoát", "đăng xuất" hoặc CTL-D, công việc con (công việc) sẽ không nhận được tiếng thở dài (cả người dùng root và reg). Tuy nhiên, khi tôi thực hiện "kill -HUP $$" để giết trường hợp bash hiện tại, các tiến trình con DID nhận được một tiếng thở dài. Sau đó tôi đã đặt huponexit và tiến trình con đã nhận được SIGHUP khi thoát.
CarpeNoctem

3

Nó sẽ được gửi SIGHUP trong các thử nghiệm của tôi:

Vỏ1:

[kbrandt@kbrandt-opadmin: ~] ssh localhost
[kbrandt@kbrandt-opadmin: ~] perl -e sleep & 
[1] 1121
[kbrandt@kbrandt-opadmin: ~] ps
  PID TTY          TIME CMD
 1034 pts/46   00:00:00 zsh
 1121 pts/46   00:00:00 perl
 1123 pts/46   00:00:00 ps

Vỏ2:

strace -e trace=signal -p1121

Shell1 Một lần nữa:

[kbrandt@kbrandt-opadmin: ~] exit
zsh: you have running jobs.
[kbrandt@kbrandt-opadmin: ~] exit
zsh: warning: 1 jobs SIGHUPed
Connection to localhost closed.

Shell2 Một lần nữa :

strace -e trace=signal -p1121
Process 1121 attached - interrupt to quit
pause()                                 = ? ERESTARTNOHAND (To be restarted)
--- SIGHUP (Hangup) @ 0 (0) ---
Process 1121 detached

Tại sao nó vẫn chạy?:
Lập trình nâng cao trong môi trường Unix bởi Stevens trình bày điều này trong phần 9.10: Các nhóm quy trình mồ côi. Phần có liên quan nhất là:

Do nhóm quy trình mồ côi khi cha mẹ chấm dứt, POSIX.1 yêu cầu mọi quy trình trong nhóm quy trình mới mồ côi bị dừng (như con của chúng ta) được gửi tín hiệu gác máy (SIGHUP) theo sau là tín hiệu tiếp tục (SIGCONT) ).

Điều này khiến đứa trẻ được tiếp tục, sau khi xử lý tín hiệu gác máy. Hành động mặc định cho tín hiệu gác máy là chấm dứt quá trình, vì vậy chúng tôi phải cung cấp bộ xử lý tín hiệu để bắt tín hiệu. Do đó, chúng tôi hy vọng printf trong hàm sig_hup sẽ xuất hiện trước printf trong hàm pr_ids.


Nhưng bạn rõ ràng đã gửi một SIGHUP tới nó ở đây; Tôi đã nói về những gì xảy ra khi bạn đăng xuất khỏi shell nơi bạn bắt đầu quá trình.
Massimo

Kết quả tương tự khi tôi nhập thoát, mặc dù tôi nhận được cảnh báo về công việc, nhưng sau đó nhập lại thoát. Tôi đã thử nghiệm điều này với ZSH.
Kyle Brandt

Tôi đang sử dụng BASH, và điều này có lẽ phụ thuộc vào vỏ. Nhưng BASH nên gửi SIGHUP cho các tiến trình con khi đăng xuất ...
Massimo

Bash gửi SIGCONT rõ ràng nếu công việc bị dừng lại, nhưng tôi xác nhận nó không gửi bất cứ thứ gì nếu công việc không bị dừng lại.
Kyle Brandt

Sử dụng Bash trên CentOS 7.1, tôi nhận được một SIGTERM được gửi đến tiến trình của mình trong một cửa sổ khác: 1.) Bắt đầu tập lệnh shell đơn giản (lặp với tiếng vang và ngủ), 2.) Control-Z nó, 3) tiến hành quá trình trong một cửa sổ khác, 4) thoát khỏi thiết bị đầu cuối ban đầu. Nó phàn nàn rằng tôi đã điều hành công việc, sau đó sau khi thoát khỏi chương trình đi bộ của tôi: $ strace -e signal -p1705 Process 1705 attached --- stopped by SIGTSTP --- --- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=791, si_uid=3000090} --- +++ killed by SIGTERM +++ Lạ, chắc chắn không phù hợp với phần trích dẫn từ Stevens.
Mike S

2

Tôi đã chạy một số thử nghiệm bằng cách sử dụng CentOS 7.1 và bash. Lưu ý rằng điều này có nghĩa huponexitofftheo mặc định và đã bị tắt trong phần lớn các thử nghiệm của tôi.

Bạn cần nohupkhi bạn bắt đầu một công việc trong một thiết bị đầu cuối, bởi vì nếu bạn đóng thiết bị đầu cuối đó mà không thoát khỏi vỏ một cách sạch sẽ , thiết bị đầu cuối sẽ gửi tín hiệu SIGHUP đến vỏ, sau đó gửi nó cho tất cả trẻ em. Nếu bạn thoát khỏi shell một cách sạch sẽ - có nghĩa là công việc phải ở trong nền để bạn có thể nhập exithoặc nhấn Control-D tại dấu nhắc lệnh - không có tín hiệu nào được gửi đến công việc nền từ bash.

Kiểm tra:

Nhà ga 1

$ echo $$
16779

Nhà ga số 2

$ strace -e signal -p16779
Process 16779 attached

(đóng thiết bị đầu cuối 1, nhìn thấy trong thiết bị đầu cuối 2):

--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=16777, si_uid=3000090} ---
rt_sigprocmask(SIG_BLOCK, [CHLD TSTP TTIN TTOU], [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_SETMASK, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_SETMASK, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], NULL, 8) = 0
rt_sigaction(SIGHUP, {SIG_DFL, [], SA_RESTORER, 0x7f7ace3d9a00}, {0x456880, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], SA_RESTORER, 0x7f7ace3d9a00}, 8) = 0
kill(16779, SIGHUP)                     = 0
rt_sigreturn()                          = -1 EINTR (Interrupted system call)
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=16779, si_uid=3000090} ---
+++ killed by SIGHUP +++

Công việc doit.sh:

#!/bin/bash

imhupped() {
        echo "HUP" >> /tmp/outfile
}

trap imhupped SIGHUP

for i in $(seq 1 6); do echo out $i >> /tmp/outfile; sleep 5; done

Bắt đầu nó trong nền trong Terminal 1:

Nhà ga 1

$ ./doit.sh &
[1] 22954

Strace nó trong Terminal 2; đóng Terminal 1 sau một vài vòng lặp:

Nhà ga số 2

$ strace -e signal -p22954
Process 22954 attached
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=22980, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f7a5d547a00}, {0x43e4b0, [], SA_RESTORER, 0x7f7a5d547a00}, 8) = 0
...
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=21685, si_uid=3000090} ---
rt_sigreturn()                          = -1 EINTR (Interrupted system call)
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=23017, si_status=SIGHUP, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
...

Đầu ra trong Terminal 3:

Nhà ga số 3

out 1
out 2
out 3
HUP
out 4
out 5
out 6

Tuy nhiên, nếu bạn thoát bash, nó chỉ đơn giản là thoát mà không gửi bất kỳ tín hiệu nào cho trẻ cả. Thiết bị đầu cuối sẽ thoát vì không còn có con, nhưng tất nhiên không có ai để HUP vì vỏ con đã biến mất. Các SIGINT, SIG_BLOCKSIG_SETMASKbạn thấy dưới đây là do sleeptrong vỏ.

Nhà ga 1

$ ./doit.sh &
26275

Nhà ga số 2

$ strace -e signal -p26275
Process 26275 attached
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26280, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGINT, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0


(..."exit" is typed in bash, notice no new signals sent...)


rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26303, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGINT, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0

Đầu 3, đầu ra

out 1
out 2
out 3
out 4
out 5
out 6

Thật thú vị, tôi đã thiết lập huponexitđể tiếp tục shopt -s huponexit; shopt(cửa hàng sau để xem xét), sau đó thực hiện thử nghiệm cuối cùng và một lần nữa bash không gửi tín hiệu cho quá trình nền . Thậm chí THÊM xen kẽ, như chúng ta đã thấy bash đã gửi tín hiệu đến quá trình nền sau khi nó nhận được nó từ một thiết bị đầu cuối đóng vào mặt nó. Có vẻ như huponexitcó liên quan gì cách này hay cách khác.

Tôi hy vọng điều này sẽ loại bỏ bất kỳ bí ẩn hoặc sự nhầm lẫn nào liên quan đến ít nhất sự bực bội của bash, về thời điểm và cách thức tín hiệu HUP được gửi. Ít nhất các bài kiểm tra của tôi là hoàn toàn có thể tái tạo, đối với tôi. Tôi rất muốn biết liệu có bất kỳ cài đặt nào khác có thể ảnh hưởng đến hành vi của bash không.

Và, như mọi khi, YSMV (Your Shell May Vary).

Phụ lục 1

Khi tôi chạy shell như exec /bin/shsau đó chạy script như /bin/sh ./doit.sh &sau đó thoát khỏi shell một cách sạch sẽ, không có tín hiệu nào được gửi đến công việc nền và nó tiếp tục chạy để hoàn thành.

Phụ lục 2

Khi tôi chạy shell như exec /bin/cshsau đó chạy script như /bin/sh ./doit.sh &sau đó thoát khỏi shell một cách sạch sẽ, không có tín hiệu nào được gửi đến công việc nền và nó tiếp tục chạy để hoàn thành.


0

Tôi sử dụng csh và các quá trình nền tiếp tục chạy cùng khi tôi đăng xuất.

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.