짧은 답변
에서 bash
(그리고 dash
) 다양한 "작업 상태"메시지는 신호 처리기에서 표시되지만 명시 적으로 검사를 필요로하지 않습니다. 이 확인은 새 프롬프트를 입력하기 전에 만 수행되며 새 명령을 입력하는 동안 사용자를 방해하지 않을 수 있습니다.
kill
프로세스가 아직 죽지 않았기 때문에 메시지 가 표시된 후 프롬프트 직전에 메시지 가 표시되지 않습니다. 이것은 kill
쉘의 내부 명령 이기 때문에 특히 가능한 조건이므로 실행이 매우 빠르며 포크가 필요하지 않습니다.
killall
대신 동일한 실험을 수행하면 일반적으로 즉시 "killed"메시지가 표시됩니다. 시간 / 컨텍스트 스위치 / 외부 명령을 실행하는 데 필요한 모든 작업으로 인해 제어가 셸로 돌아 오기 전에 프로세스가 종료 될 때까지 지연 시간이 길어짐 .
matteo@teokubuntu:~$ dash
$ sleep 60 &
$ ps
PID TTY TIME CMD
4540 pts/3 00:00:00 bash
4811 pts/3 00:00:00 sh
4812 pts/3 00:00:00 sleep
4813 pts/3 00:00:00 ps
$ kill -9 4812
$
[1] + Killed sleep 60
$ sleep 60 &
$ killall sleep
[1] + Terminated sleep 60
$
긴 대답
dash
우선, dash
소스를 살펴 보았습니다 . 왜냐하면 dash
동일한 동작을 나타내며 코드가보다 간단하기 때문 bash
입니다.
위에서 말했듯이, 작업 상태 메시지는 신호 처리기 ( "정상적인"셸 제어 흐름을 방해 할 수 있음)에서 방출되지 않지만 수행 된 명시 적 검사 ( showjobs(out2, SHOW_CHANGED)
호출 dash
) 의 결과입니다. REPL 루프에서 사용자에게 새로운 입력을 요청하기 전에 만.
따라서 셸이 사용자 입력을 기다리는 동안 차단되면 해당 메시지가 생성되지 않습니다.
자살 직후에 검사가 왜 프로세스가 실제로 종료되었다고 표시하지 않습니까? 위에서 설명한 것처럼 아마도 너무 빠르기 때문일 것입니다. kill
는 쉘의 내부 명령이므로 실행이 매우 빠르며 포크가 필요하지 않으므로 kill
검사가 수행 된 직후 프로세스가 여전히 활성 상태입니다 (또는 적어도 여전히 종료되고 있음).
bash
bash
보다 복잡한 쉘인 예상대로 까다 로웠으며 약간의 gdb
fu가 필요했습니다 .
해당 메시지가 생성 될 때의 역 추적은 다음과 같습니다.
(gdb) bt
#0 pretty_print_job (job_index=job_index@entry=0, format=format@entry=0, stream=0x7ffff7bd01a0 <_IO_2_1_stderr_>) at jobs.c:1630
#1 0x000000000044030a in notify_of_job_status () at jobs.c:3561
#2 notify_of_job_status () at jobs.c:3461
#3 0x0000000000441e97 in notify_and_cleanup () at jobs.c:2664
#4 0x00000000004205e1 in shell_getc (remove_quoted_newline=1) at /Users/chet/src/bash/src/parse.y:2213
#5 shell_getc (remove_quoted_newline=1) at /Users/chet/src/bash/src/parse.y:2159
#6 0x0000000000423316 in read_token (command=<optimized out>) at /Users/chet/src/bash/src/parse.y:2908
#7 read_token (command=0) at /Users/chet/src/bash/src/parse.y:2859
#8 0x00000000004268e4 in yylex () at /Users/chet/src/bash/src/parse.y:2517
#9 yyparse () at y.tab.c:2014
#10 0x000000000041df6a in parse_command () at eval.c:228
#11 0x000000000041e036 in read_command () at eval.c:272
#12 0x000000000041e27f in reader_loop () at eval.c:137
#13 0x000000000041c6fd in main (argc=1, argv=0x7fffffffdf48, env=0x7fffffffdf58) at shell.c:749
죽은 작업 및 공동 확인 전화. 이다 notify_of_job_status
(그 이상 또는 이하의 동등 물 showjobs(..., SHOW_CHANGED)
에 dash
); # 0- # 1은 내부 작업과 관련이 있습니다. 6-8은 yacc 생성 파서 코드이다; 10-12는 REPL 루프입니다.
여기서 흥미로운 곳은 # 4, 즉 notify_and_cleanup
전화가 오는 곳입니다. 그 보인다 bash
는 달리, dash
각 문자는 명령 줄에서 읽을에서 종료 작업을 확인 할 수 있지만 여기에 내가 무엇을 발견 :
/* If the shell is interatctive, but not currently printing a prompt
(interactive_shell && interactive == 0), we don't want to print
notifies or cleanup the jobs -- we want to defer it until we do
print the next prompt. */
if (interactive_shell == 0 || SHOULD_PROMPT())
{
#if defined (JOB_CONTROL)
/* This can cause a problem when reading a command as the result
of a trap, when the trap is called from flush_child. This call
had better not cause jobs to disappear from the job table in
that case, or we will have big trouble. */
notify_and_cleanup ();
#else /* !JOB_CONTROL */
cleanup_dead_jobs ();
#endif /* !JOB_CONTROL */
}
따라서 대화식 모드 에서는 사용자가 명령을 입력하는 것을 방해하지 않도록 새 프롬프트가 제공 될 때까지 검사를 지연시키는 것이 의도 됩니다. 에서 바로 다음에 새 프롬프트를 표시 할 때 검사에서 데드 프로세스를 발견하지 못하는 이유에 kill
대해서는 이전 설명이 그대로 유지됩니다 (프로세스는 아직 종료되지 않았습니다).
pid="$(sh -c 'cat "$fileName" |less & echo ${!}')"
미만 표시 실 거예요