Вы посмотрели на свои журналы производительности для наблюдения, каково узкое место? Я предложил бы включить контроль диска ввод-вывод, сети, загрузка процессора и подкачка страниц памяти, чтобы запуститься с и видеть, привязывает ли один из них. Это затем дало бы Вам признак того, что необходимо обновить для увеличения производительности.
Ответ найден.
Для Bash это зависит от huponexit
опция оболочки, которая может быть просмотрена и/или устанавливает использование встроенного shopt
команда.
Похож на это, опции прочь по умолчанию, по крайней мере, в основанных на Redhat системах.
Больше информации о странице справочника Bash:
Оболочка выходит по умолчанию по получении SIGHUP. Перед выходом интерактивная оболочка снова посылает SIGHUP всем заданиям, работая или остановилась. Остановленные задания отправляются SIGCONT, чтобы гарантировать, чтобы они получили SIGHUP. Чтобы препятствовать тому, чтобы оболочка отправила сигнал в конкретное задание, это должно быть удалено из таблицы заданий с отрицанием встроенного (см. SHELL ВСТРОЕННЫЕ КОМАНДЫ ниже), или отмеченный для не получения использования SIGHUP отрицают-h.
Если опция оболочки huponexit была установлена с shopt, удар отправляет SIGHUP во все задания, когда интерактивная оболочка входа в систему выходит.
Это будет отправлено SIGHUP в моих тестах:
Shell1:
[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
Shell2:
strace -e trace=signal -p1121
Shell1 снова:
[kbrandt@kbrandt-opadmin: ~] exit
zsh: you have running jobs.
[kbrandt@kbrandt-opadmin: ~] exit
zsh: warning: 1 jobs SIGHUPed
Connection to localhost closed.
Shell2 снова:
strace -e trace=signal -p1121
Process 1121 attached - interrupt to quit
pause() = ? ERESTARTNOHAND (To be restarted)
--- SIGHUP (Hangup) @ 0 (0) ---
Process 1121 detached
Почему это все еще работает?:
Усовершенствованное Программирование в Среде Unix Stevens покрывает это под разделом 9.10: Осиротевшие Группы Процесса. Самое соответствующее раздел быть:
Так как группа процесса является осиротевшей, когда родитель завершается, POSIX.1 требует, что каждый процесс в недавно осиротевшей группе процесса, которая останавливается (поскольку наш ребенок) быть отправленным сигнал зависания (SIGHUP), сопровождаемый продолжать сигналом (SIGCONT).
Это заставляет ребенка быть продолженным после обработки сигнала зависания. Действие по умолчанию для сигнала зависания должно завершить процесс, таким образом, мы должны обеспечить обработчик сигналов для ловли сигнала. Мы поэтому ожидаем, что printf в функции sig_hup появится перед printf в функции pr_ids.
أجريت بعض الاختبارات باستخدام CentOS 7.1 و bash. لاحظ أن هذا يعني أن huponexit
تم إيقاف على
افتراضيًا ، وتم إيقافه لمعظم اختباراتي.
أنت بحاجة إلى nohup
عندما تبدأ وظيفة في الطرفية ، لأن إذا أغلقت ذلك الطرف دون الخروج من القشرة بشكل نظيف ، فإن المحطة ترسل إشارة SIGHUP إلى الغلاف ، والتي ترسلها بعد ذلك إلى جميع الأطفال. إذا خرجت من shell بشكل نظيف - مما يعني أن المهمة يجب أن تكون بالفعل في الخلفية حتى تتمكن من كتابة خروج
أو الضغط على Control-D في موجه الأوامر - لا يتم إرسال أي إشارات من أي نوع إلى وظيفة الخلفية من bash .
الاختبار:
Terminal 1
$ echo $$
16779
Terminal 2
$ strace -e signal -p16779
Process 16779 attached
(إغلاق المحطة 1 ، كما هو موضح في المحطة 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 +++
Job 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
ابدأ في الخلفية في المبنى رقم 1:
المبنى 1
$ ./doit.sh &
[1] 22954
ضعها في المبنى 2 ؛ أغلق Terminal 1 بعد حلقتين:
Terminal 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
...
الإخراج في Terminal 3:
Terminal 3
out 1
out 2
out 3
HUP
out 4
out 5
out 6
ومع ذلك ، إذا خرجت من bash
، فإنه يخرج ببساطة دون إرسال أي إشارة للطفل على الإطلاق. ستخرج المحطة الطرفية لأنه لم يعد لديها طفل ، ولكن بالطبع لا يوجد أحد لـ HUP لأن الغلاف الفرعي قد اختفى بالفعل. SIGINT
، SIG_BLOCK
و SIG_SETMASK
التي تراها أدناه ترجع إلى السكون
في الغلاف.
المحطة 1
$ ./doit.sh &
26275
المحطة 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
المحطة 3 ، المخرجات
out 1
out 2
out 3
out 4
out 5
out 6
ومن المثير للاهتمام ، أنني قمت بتعيين huponexit
ليكون على shopt -s huponexit ؛ shopt
(الخيار الأخير للمراجعة) ، ثم أجرى الاختبار الأخير ، ومرة أخرى لم يرسل bash أي إشارة لعملية الخلفية . والأكثر شيوعًا ، كما رأينا أن bash أرسل الإشارة إلى عملية الخلفية بعد أن استقبلها من محطة أغلقت في وجهها.يبدو كما لو أن huponexit
ليس له تأثير بطريقة أو بأخرى.
آمل أن يزيل هذا أي غموض أو ارتباك فيما يتعلق على الأقل بعجوبة باش ، حول متى وكيف يتم إرسال إشارة HUP. على الأقل كانت اختباراتي قابلة للتكرار تمامًا ، بالنسبة لي. سأكون مهتمًا بمعرفة ما إذا كانت هناك أي إعدادات أخرى قد تؤثر على سلوك bash.
وكالعادة ، YSMV (قد يختلف شل الخاص بك).
الملحق 1
عندما أقوم بتشغيل shell كـ exec / bin / sh
، ثم قم بتشغيل البرنامج النصي كـ / bin / sh ./doit.sh &
، ثم اخرج من الغلاف بشكل نظيف ، ولا يتم إرسال أي إشارات إلى وظيفة الخلفية ويستمر للتشغيل حتى الاكتمال.
الملحق 2
عندما أقوم بتشغيل قذيفة كـ exec / bin / csh
، قم بتشغيل البرنامج النصي كـ / bin / sh ./doit.sh &
، ثم اخرج من الغلاف بشكل نظيف ، فلن يتم إرسال أي إشارات إلى وظيفة الخلفية ويستمر العمل حتى الاكتمال.