트랩을 사용하여 종료 확인


9

Ctrl+C사용자에게 확인을 요청하는 신호 를 포착하려고합니다 . 트래핑 부분이 제대로 작동합니다. 그러나 일단 신호가 잡히면 정상적인 실행으로 되돌아 가지 않습니다. 대신 스크립트를 종료합니다. 사용자가 no를 누를 때 실행을 재개하는 방법.

여기 내 코드가 있습니다

hell()
{
echo "Do you want to quit? Press 1 for yes and 0 for no";
read n;
if [ $n == 1 ]; then
exit 1;
fi
}

trap "hell" SIGINT

find /

답변:


12

무슨 일이야

당신이 키를 누르면 Ctrl+ CSIGINT신호 전체에 전달되는 전경 프로세스 그룹 . 여기서는 find프로세스와 호출 셸 프로세스 모두로 전송됩니다 . find즉시 종료하여 반응하고 쉘은 트랩을 호출하여 반응합니다.

트랩의 코드가 반환되면 (즉 exit, 호출하지 않음 ) 신호에 의해 중단 된 명령 다음에 명령이 실행됩니다. 여기에서 find명령이 스크립트의 끝에 도달하면 스크립트는 즉시 종료됩니다. 그러나 다른 명령을 추가하여 0과 1을 입력하는 것의 차이점을 볼 수 있습니다.

find /
echo "find returned $?"

원하는 것을 수행하는 방법 (아마도하지 말아야 할 것)

당신이 원하는 것을 할 수 있습니다; 그러나 내 대답 의이 부분은 실제 문제를 해결하는 것보다 쉘 프로그래밍을 발견하는 것에 관한 것입니다.

  • 디자인 문제로서, 재시작 가능한 신호는 일반적으로 쉘 스크립트가 일반적으로 사용하는 비교적 간단한 프로그램에서 기대하는 것이 아닙니다. Ctrl+ C는 스크립트를 죽일 것으로 예상 됩니다.
  • 아래에서 볼 수 있듯이 쉘의 기능을 약간 확장합니다.

당신이 살인을 피하려면 find, 당신은 그것을 시작하는 데 필요한 배경 : find / &. 그런 다음 wait내장 을 사용하여 정상적으로 종료 될 때까지 기다리십시오. 신호는 wait내장 신호를 차단하며 전파하려는 신호를 수신 할 때까지 루프에서 실행할 수 있습니다. 그런 다음 kill작업을 종료 하는 데 사용 하십시오.

hell () {
  echo "Do you want to quit? Press 1 for yes and 0 for no"
  read n
  if [ "$n" = 1 ]; then
    # Kill the job if it's running, then exit
    if [ -n "$job_pid" ]; then kill $job_pid; fi
    exit 1
  fi
}

job_pid=
trap "hell" SIGINT

# Start a demo job in the background
for i in 1 2 3 4 5; do date; sleep 1; done &
job_pid=$!
# Call wait in a loop; wait will return 0 if the job exits, and 128+$signum if interrupted by a signal.
while ! wait; do
  echo "resuming wait"
done
job_pid=
echo last exit code: $?

셸에서이 방법에는 제한이 있습니다.

  • 경쟁 조건이 있습니다. 작업이 끝나고 라인 바로 전에 Ctrl+ 를 누르면 신호 핸들러가 kill을 시도 하지만 프로세스는 더 이상 존재하지 않습니다 ( 이미 좀비로 도 이미 수확 했기 때문에 ). 다른 프로세스에서 ID를 재사용했을 수 있습니다. 이것은 쉘에서 쉽게 고칠 수 없습니다 ( ?에 대한 핸들러를 설정하여 ).Cjob_pid=$jobpidwaitSIGCHLD
  • 작업에서 반송 상태가 필요한 경우 wait $job_pid양식 을 사용해야합니다 . 그러나 " wait신호에 의해 중단되었습니다"와 "작업이 신호에 의해 종료되었습니다"( "반환 상태가 ≥128 인 자체 작업으로 종료 됨") 와 구별 할 수 는 없지만 셸의 일반적인 사실입니다. 프로그램 작성).
  • 여러 하위 작업으로 확장되면 쉽게 확장되지 않습니다. 트랩과 신호의 동작은 대부분의 쉘 구현에서 기본을 넘어 설 때 종종 놀라운 일입니다 (ksh 만 잘 수행함).

이러한 한계를 극복하려면 Perl 또는 Python과 같은 더 멋진 언어를 사용하십시오.

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