SIGINT 등을 잡을 때 종료 코드를 유지 하시겠습니까? 변경됩니다. 이제 이것은 아마도 실제 세계에서 차이를

http://linuxcommand.org/wss0160.php#trap 에서 trap설명한 것과 같이 사용 하여 종료하기 전에 ctrl-c (또는 유사한) 및 정리를 잡으면 종료 코드가 변경됩니다.

이제 이것은 아마도 실제 세계에서 차이를 만들지 않을 것입니다 (예 : 종료 코드가 이식 가능하지 않고 프로세스가 종료 될 때 기본 종료 코드 에서 논의 된 것처럼 항상 명확하지는 않기 때문에 ) ? 실제로이를 방지하고 대신 중단 된 스크립트에 대한 기본 오류 코드를 반환 할 방법이 없습니까?

예 (bash에서 내 질문은 bash 특정으로 간주되어서는 안됩니다) :

#!/bin/bash
trap 'echo EXIT;' EXIT
read -p 'If you ctrl-c me now my return code will be the default for SIGTERM. ' _
trap 'echo SIGINT; exit 1;' INT
read -p 'If you ctrl-c me now my return code will be 1. ' _

산출:

$ ./test.sh # doing ctrl-c for 1st read
If you ctrl-c me now my return code will be the default for SIGTERM.
$ echo $?
130
$ ./test.sh # doing ctrl-c for 2nd read
If you ctrl-c me now my return code will be the default for SIGTERM.
If you ctrl-c me now my return code will be 1. SIGINT
EXIT
$ echo $?
1

(POSIX 준수를 위해 제거하도록 편집되었습니다.)

(대신 bash 스크립트로 다시 편집하면 내 질문은 쉘별로 다릅니다.)

휴대 할 수없는 “SIGINT”를 위해 휴대용 “INT”를 트랩에 사용하도록 편집했습니다.

쓸모없는 중괄호를 제거하고 잠재적 솔루션을 추가하도록 편집되었습니다.

최신 정보:

하드 코드 된 오류 코드로 종료하고 EXIT를 트랩하여 간단하게 해결했습니다. 오류 코드가 다르거 나 EXIT 트랩을 사용할 수 없지만 내 경우에는 충분하기 때문에 특정 시스템에서 문제가 될 수 있습니다.

trap cleanup EXIT
trap 'exit 129' HUP
trap 'exit 130' INT
trap 'exit 143' TERM



답변

정리 처리기 에서 EXIT 처리기를 변경하기 만하면 됩니다. 예를 들면 다음과 같습니다.

#!/bin/bash
cleanup() {
    echo trapped exit
    trap 'exit 0' EXIT
}
trap cleanup EXIT
read -p 'If you ctrl-c me now my return code will be the default for SIGTERM. '


답변

실제로 bash의 내부 인터럽트는 bash가 read실행하는 명령을 인터럽트하는 것과 약간 다릅니다. 일반적으로을 입력 trap하면 $?이 설정되어 있으며 동일한 값으로 유지하고 종료 할 수 있습니다.

trap 'rc=$?; echo $rc SIGINT; exit $rc' INT
trap 'rc=$?; echo $rc EXIT; exit $rc' EXIT

같은 명령을 실행할 때 스크립트가 중단 된 경우 sleep
또는 같은 심지어 내장을 wait, 당신은 볼 것이다

130 SIGINT
130 EXIT

그리고 종료 코드를 위해, 그러나 130 인 read -p것 같다, $?(어쨌든 bash는 4.3.42의 내 버전) 0입니다.


read내 릴리스의 변경 파일에 따라 신호 처리 중일 수 있습니다 … (/ usr / share / doc / bash / CHANGES)

이 버전 bash-4.3-alpha와 이전 버전 bash-4.2-release 사이의 변경 사항.

  1. 배쉬의 새로운 기능

    아르 자형. Posix 모드에있을 때 트랩 된 신호에 의해 ‘판독’이 중단 될 수 있습니다. 트랩 처리기를 실행 한 후 읽기는 128+ 신호를 반환하고 부분적으로 읽은 입력을 버립니다.


답변

$?트랩 핸들러에 들어가면 일반적인 신호 종료 코드를 사용할 수 있습니다 .

sig_handler() {
    exit_status=$?  # Eg 130 for SIGINT, 128 + (2 == SIGINT)
    echo "Doing signal-specific up"
    exit "$exit_status"
}
trap sig_handler INT HUP TERM QUIT

별도의 EXIT 트랩이있는 경우 동일한 방법을 사용할 수 있습니다. 신호 처리기에서 전달 된 종료 상태 (있는 경우)를 즉시 정리 한 다음 저장된 종료 상태를 리턴하십시오.


답변

SIGINT에 의한 이탈을 시뮬레이션하기에 오류 코드로는 충분하지 않습니다. 지금까지 아무도 이것을 언급하지 않은 것에 놀랐습니다. 추가 자료 : https://www.cons.org/cracauer/sigint.html

올바른 방법은 다음과 같습니다

for sig in EXIT ABRT HUP INT PIPE QUIT TERM; do
    trap "cleanup;
          [ $sig  = EXIT ] && normal_exit_only_cleanup;
          [ $sig != EXIT ] && trap - $sig EXIT && kill -s $sig $$
         " $sig
done

이것은 Bash, Dash 및 zsh와 함께 작동합니다. 추가 이식성을 위해서는 숫자 신호 사양을 사용해야합니다 (반면에 zsh는 kill명령에 문자열 매개 변수가 필요합니다 ).

또한 EXIT신호 의 특수 처리에 유의하십시오 . 이것은 일부 쉘 (즉, Bash) EXIT이 모든 신호 에 대해 트랩을 실행하기 때문입니다 (해당 신호에 트랩을 정의한 후). EXIT트랩을 리셋 하면 방지 할 수 있습니다.

“정상”종료에서만 코드 실행

이 검사를 [ $sig = EXIT ]통해 정상적인 (신호가없는) 종료에서만 코드를 실행할 수 있습니다. 그러나 모든 신호에는 트랩이 있어야 트랩을 재설정 할 수 있습니다 EXIT. normal_exit_only_cleanup그렇지 않은 신호에 대해서도 호출됩니다. 또한를 통해 이탈로 실행됩니다 set -e. 이것은 ERR(Dash에서 지원하지 않는) 트 랩핑 하고에 확인 표시 [ $sig = ERR ]를 추가하여 해결할 수 있습니다 kill.

단순화 된 배쉬 전용 버전

반면에,이 동작은 Bash에서 간단히 할 수 있음을 의미합니다

trap cleanup EXIT

정리 코드를 실행하고 종료 상태를 유지합니다.

편집

  • “EXIT가 모든 것을 포착”하는 정교한 Bash의 동작

  • 갇힐 수없는 KILL 신호 제거

  • 신호 이름에서 SIG 접두사 제거

  • 시도하지 마십시오 kill -s EXIT

  • set -e/ ERR을 고려


답변