일시 중단 된 후 while 루프가 중지되는 이유는 무엇입니까?


10

bash를 사용하고 while 루프를 일시 중단하면 루프가 재개 된 후에 중지되는 이유는 무엇입니까? 아래의 간단한 예입니다.

$ while true; do echo .; sleep 1; done
.
.
^Z
[1]+  Stopped                 sleep 1
$ fg
sleep 1
$

나는 신호에 익숙하며 이것이 bash의 자연스러운 행동 일 수 있다고 생각합니다. 그러나 왜이 특정 방식으로 동작하는지 이해하고 싶습니다.


인터럽트를 처리해야하고 $?리턴시 이를 정확하게 반영해야 하기 때문에 true그렇지 않습니다 true. 아마. 나는 생각한다.
mikeserv

1
이 의견에 깃발이 표시되지 않기를 바라지 만 Unix koan 스타일의 다른 질문으로 귀하의 질문에 답변 해 드리겠습니다. 대답은 그가 더 이상 놀이터에서 그가 싸움을 시작할 수있는 능력이 없기 때문입니다. 따라서 문제의 행동은 단순히 중단되었습니다.
rubynorails

명령을 중지하면 루프가 끊어집니다. 그런 다음 루프가 아닌 단일 절전 1 명령을 재개합니다.
123

답변:


10

이것은 여러 쉘에서 버그처럼 보이며 ksh93zsh에서 예상대로 작동합니다 .

배경:

대부분의 쉘은 메인 쉘 내부에서 while 루프를 실행하는 것으로 보입니다.

로그인하지 않은 쉘로 ^ Z를 입력하면 Bourne Shell 이 전체 쉘을 일시 중단합니다.

bash 는을 일시 중단 sleep한 다음 while 루프를 떠나 새로운 쉘 프롬프트를 인쇄합니다.

대시 는이 명령을 일시 중지 할 수 없게 만듭니다

ksh93을 사용하면 상황이 매우 다릅니다.

ksh93 은 명령이 처음으로 시작되는 동안 동일하게 수행되지만 sleepksh93의 buitin 과 마찬가지로 ksh93에는 while 루프가 기본 쉘을 분기 한 다음 ^ Z를 입력 할 때 일시 중단하는 핸들러가 있습니다.

당신이 경우 경우 ksh93 나중에 유형 fg의 아동 떨어져 포크 것을 여전히 루프가 계속 실행됩니다.

bash 및 ksh93의 작업 제어 메시지를 비교할 때 주요 차이점이 있습니다.

bash 보고서 :

[1]+ Stopped sleep 1

그러나 ksh93 보고서 :

^Z[1] + Stopped while true; do echo .; sleep 1; done

zshksh93 과 유사하게 작동합니다

두 쉘 모두 ^ Z를 입력하지 않는 한 단일 프로세스 (주 쉘)와 ^ Z를 입력 한 후 두 개의 쉘 프로세스가 있습니다.


dash루프가 종료 될 때 실제로 신호를 처리 하지 않습니다 . 에 [d]?ash소스 코드가 이러한 매크로 모두 INTONINTOFF가 전반에 걸쳐 분산 및에있는 동안 일반적으로 수신 된 신호 INTOFF의 상태 정말로에서 처리됩니다 (또는 정도) INTON . 어쨌든, 나는 당신이 더 잘 알고 있다고 생각하는 단지 호기심이 많은 이유입니다-그것은 훌륭한 대답입니다. 감사합니다.
mikeserv

나는 대시를 거의 사용하지 않으며 최근에 bash, ksh93 및 Bourne Shell과의 성능 비교를 위해 가져오고 컴파일했습니다. 이러한 테스트를 수행하는 동안 멀티 바이트 문자에 대한 지원이 포함되어 있지 않기 때문에 대시가 주로 빠른 것 같습니다. 에서 싱글 sleep 100을 일시 중지 및 재개 할 수 있으므로이 명령의 문제점 dashdash알고 작업 제어를 선택적으로 비활성화 하는 것 같습니다 .
schily

따라서 테스트에서 dash멀티 바이트 처리를 삭제하여 다른 쉘의 성능 과 같을 수 있습니까? 예, dash작업 제어를 지원하지만 표준에서는 대화식 쉘이 TSTP를 무시해야하며 대화식 터미널에서 현재 쉘에서 while 루프를 실행하는 것이 다른 대화식 쉘과 다름 없다고 말합니다.
mikeserv

나는 이것을 정확하게 테스트하지는 않았지만 대시가 ksh93 또는 Bourne Shell보다 더 많은 시스템 CPU 시간을 소비하지만 (주로 더 많은 fork () 호출을 발행하기 때문에) 더 많은 사용자 CPU 시간을 사용한다는 것을 알 수 있습니다. Bourne Shell의 내 버전과 비교 한 CPU 시간. Bourne Shell에서 사용자 CPU 시간을 줄이려고 노력하면서이 시간의 대부분은 멀티 바이트 변환에 소비된다는 것을 알고 있습니다.
schily

4

나는 Bash의 공동 저자 중 한 사람 에게이 문제에 대해 썼으며 다음은 그의 대답입니다.

실제로 버그는 아니지만 확실히 경고입니다.

여기서는 쉘 명령과는 다른 단위 단위 인 프로세스를 일시 중단한다는 아이디어입니다. 프로세스가 일시 중단되면 쉘로 돌아갑니다 (0이 아닌 상태로 루프 테스트 인 프로세스를 중지하면 결과가 나타남). , 중지 된 프로세스를 남겨 둡니다. Bash는 작업이 중지 될 때 루프에서 벗어날 것을 선택하고 항상 선택했습니다. 루프를 계속하는 것이 원하는 것은 아닙니다.

일부 다른 쉘은 SIGTSTP로 인해 프로세스가 일시 중단 될 때 쉘 사본을 분기하고 해당 프로세스를 중지하는 등의 작업을 수행합니다. Bash는 이점을 보증하는 것보다 더 복잡해 보이지는 않지만 누군가가 해당 코드를 패치로 제출하려면 변경 사항을 통합하는 방법을 살펴볼 것입니다.

누구든지 패치를 제출하려면 매뉴얼 페이지에있는 이메일 주소를 사용하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.