이 차이가 왜 중요한가요? 아래 코드에서 두 블록의 차이점은 마지막 줄입니다.
#!/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/echo
vs를 사용하여 테스트했습니다 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 +++