프로세스를 종료한 후 bash가 "항상 그런 것은 아님"이 "종료됨" 메시지를 표시하는 이유는 무엇입니까? [복사]

프로세스를 종료한 후 bash가 "항상 그런 것은 아님"이 "종료됨" 메시지를 표시하는 이유는 무엇입니까? [복사]

이 차이가 왜 중요한가요? 아래 코드에서 두 블록의 차이점은 마지막 줄입니다.

#!/bin/bash
if [[ -n "$1" ]]; then
    sleep 1 &
    p=$!
    kill $p &> /dev/null
else
    sleep 1 &
    p=$!
    kill $p &> /dev/null
    /bin/true # This line is the sole difference.
fi

이름을 지정 a.sh하면 (내 Linux 컴퓨터에서) 얻을 수 있습니다.

$ ./a.sh
/a.sh: line 16: 18103 Terminated              sleep 1
$ ./a.sh foo
$ # no "Terminated" message

두 번째 사건은 왜 소식이 없나요? Bash의 기본 동작은 "Termied"(이 질문을 봤어요).

( p=$!실제 코드에서는 를 사용하고 있지만 위의 경우에는 를 사용할 수 있습니다 kill $!.)

편집하다:세르게이 콜로디아즈네문제를 언급해주세요"진실은 왜 그렇게 거짓인가?(주제에서 약간 벗어났지만 읽기에 흥미롭습니다.) 안타깝게도 이 댓글에 해당하는 답변이 삭제되었으므로 여기에 기록하겠습니다. 감사합니다. Sergiy.

답변1

~에 따르면마테오 이탈리아의 답변:

대조적으로, killall을 사용하여 동일한 실험을 수행하면 일반적으로 즉시 "killed" 메시지가 생성됩니다.시간/컨텍스트 스위치/외부 명령을 실행하는 데 필요한 모든 것은 제어권이 셸로 반환되기 전에 프로세스를 종료할 만큼 충분히 긴 지연을 유발합니다.

즉, /bin/true외부 호출로 인해 발생하는 지연을 통해 쉘이 메시지를 인쇄할 수 있게 됩니다.

또한 /bin/echovs를 사용하여 테스트했습니다 echo.

#!/bin/bash
if [[ -n "$1" ]]; then
    sleep 1 &
    p=$!
    kill $p &> /dev/null
    /bin/echo "a line"
else
    sleep 1 &
    p=$!
    kill $p &> /dev/null
fi

다음 스크립트를 사용하세요.

$ bash ./mystery.sh 
$ bash ./mystery.sh foo
a line
./mystery.sh: line 11: 10361 Terminated              sleep 1

내장 echo:

$ bash ./mystery.sh 
$ bash ./mystery.sh foo
a line

즉, 외부 실행 파일이 호출된다는 사실은 마지막 하위 프로세스가 반환될 때 셸이 하위 프로세스와 백그라운드 작업에 대한 검사를 수행하도록 강제합니다. 다음의 경우:

if [[ -n "$1" ]]; then
    sleep 1 &
    p=$!
    kill $p &> /dev/null

원본 스크립트에서는 추가 명령이 호출되지 않고 마지막 내장 명령만 호출됩니다.


이 외에도 몇 가지 테스트를 실행했습니다 strace.

상위 프로세스가 종료되고 하위 프로세스를 기다리지 않는 것 같습니다. 즉, 쉘의 상위 프로세스가 너무 일찍 종료되었습니다.명시적인 검사를 수행합니다.

$ strace -s 1024 -e kill bash mystery.sh 
kill(9830, SIGTERM)                     = 0
mystery.sh: line 11:  9830 Terminated              sleep 1
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=9830, si_uid=1000, si_status=SIGTERM, si_utime=0, si_stime=0} ---
+++ exited with 0 +++
$ strace -s 1024 -e kill bash mystery.sh  foo
kill(9839, SIGTERM)                     = 0
+++ exited with 0 +++

위치 매개변수로 추적할 때 대기 호출도 없다는 점은 주목할 가치가 있습니다.

$ strace -s 1024 -e kill,wait4 bash mystery.sh  foo
kill(9910, SIGTERM)                     = 0
+++ exited with 0 +++
$ strace -s 1024 -e kill,wait4 bash mystery.sh
kill(9916, SIGTERM)                     = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=9916, si_uid=1000, si_status=SIGTERM, si_utime=0, si_stime=0} ---
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGTERM}], WNOHANG, NULL) = 9916
wait4(-1, 0x7ffe8e5bb110, WNOHANG, NULL) = -1 ECHILD (No child processes)
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 9917
mystery.sh: line 11:  9916 Terminated              sleep 1
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=9917, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, 0x7ffe8e5bb250, WNOHANG, NULL) = -1 ECHILD (No child processes)
+++ exited with 0 +++

관련 정보