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 사이의 변경 사항.
배쉬의 새로운 기능
아르 자형. 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을 고려