bash 의 신호 처리 메커니즘
신호
Signal
는 운영 체제 에서 자주 사용 하 는 프로 세 스 통신 수단 으로 주로 특정한 사건 의 발생 을 묘사 하 는데 프로 세 스 가 신 호 를 받 을 때 다음 과 같은 몇 가지 처리 방식 이 있다.signal
시스템 에 사용자 정의 반전 함 수 를 호출 합 니 다. 프로 세 스 는 신 호 를 받 을 때 이 반전 함 수 를 실행 합 니 다. signal
시스템 호출 전달 SIG_IGN
, 커 널 은 이 신 호 를 직접 버 리 기 때문에 목표 프로 세 스 는 이 신 호 를 받 지 못 합 니 다. signal
시스템 호출 전송 SIG_DFL
에 이 신호 처리 방식 을 기본 값 으로 복원 할 수 있 습 니 다. signal(SIGINT, SIG_IGN); //
signal(SIGTERM, SIG_DFL); //
signal(SIGSTOP, m_handler); //
Linux
에서 신호 의 전송 은 sigqueue
, kill
, raise
시스템 호출 에 의존 하고 신호 의 처리 상 태 는 목표 프로 세 스 task_struct
의 signal
변수 에 기록 되 어 있 으 며 이 변수의 유형 은 sigset_t
이 고 한 사람 당 하나의 신 호 를 저장 하 는 처리 상태 이기 때문에 신호 비트 맵 signal bitmap
이 라 고도 불 린 다. 발생 generate
과 배달 delivery
에 있다.사이 의 신호 상 태 는 미결 pending
로 표 시 됩 니 다. 목표 프로 세 스 가 짧 은 시간 에 대량의 중복 신 호 를 받 거나 sigpending
시스템 호출 이 특정한 신 호 를 막 을 때 목표 프로 세 스 신호 비트 맵 에서 이 신호 의 상 태 는 미결 로 변 합 니 다. Linux 5.3.0
에서 미결 상태 에 있 는 신호 에 대해 두 가지 처리 전략 이 있 습 니 다.Unix
시스템 의 처리 전략 입 니 다. 호환성 을 확보 하기 위해 Linux 5.3.0
에서 번호 가 1-31
인 신 호 는 버 림 처리 전략 을 따 릅 니 다. 즉, 사용 sigqueue
이 신 호 를 보 내 도 줄 을 서지 않 습 니 다. 신 호 를 잃 어 버 릴 가능성 이 있 기 때문에 전략 에 따라 처리 하 는 신 호 를 믿 을 수 없 는 신호 라 고 부 릅 니 다. POSIX
에 따라 비 실시 간 신호 라 고 부 릅 니 다. Linux
에서 신호 처리 방식 을 개 선 했 습 니 다. 커 널 은 목표 프로 세 스 task_struct
에서 신호 대기 열 을 유지 합 니 다. 커 널 이 신 호 를 받 았 고 목표 프로 세 스 에서 이 신호 상태 가 미결 이면 새로 발생 한 신 호 를 목표 프로 세 스 의 신호 대기 열 에 넣 습 니 다.이렇게 걸 려 있 는 신호 개수 가 커 널 이 설정 한 상한 선 을 초과 하지 않 으 면 이론 적 으로 잃 어 버 리 지 않 는 다. Linux 5.3.0
에서 번호 32-64
의 신 호 는 줄 서기 처리 전략 을 따 르 기 때문에 신뢰성 있 는 신호 라 고도 불 린 다. POSIX
에 따 르 면 실시 간 신호 라 고 불 린 다. 대부분의
Linux
발행 판 은 man 7 signal
을 통 해 현재 시스템 에서 지원 하 는 신호 종 류 를 볼 수 있 고 kill -l
모든 신호 와 해당 하 는 숫자 를 볼 수 있 습 니 다. 그 중에서 우리 가 자주 사용 하 는 것 은:(2) SIGINT
: 프론트 데스크 에 있 는 실행 중인 프로 세 스에 보 내 는 키보드 인 터 럽 트 신호, 종료 interrupt
, 일반 대응 Ctrl + C
. (19) SIGSTOP
: 무시 할 수 없 는 정지 신 호 는 프로 그래 밍 방식 으로 보 내 는 신호 입 니 다. (20) SIGTSTP
: 정지 신호, 현재 퀘 스 트 stop
를 백 스테이지 에 올 리 고 통제 권 을 shell
에 게 넘 기 며 일반 대응 Ctrl + Z
(9) SIGKILL
: 차단 되 거나 처리 되 거나 무시 되 는 신 호 는 보통 특정한 프로 세 스 를 강제로 죽 이 는 데 사 용 됩 니 다. kill -9
(15) SIGTERM
: 프로그램 종료 terminate
신 호 는 SIGKILL
와 달리 이 신 호 는 차단 되 고 처 리 될 수 있 습 니 다. 보통 프로그램 이 정상적으로 종료 하도록 요구 합 니 다. shell
명령 kill
이 부족 하면 이 신 호 를 발생 시 킵 니 다.(14) SIGALRM
: (1) SIGHUP
: 이 신 호 는 사용자 단말기 연결 (정상 또는 비정 상) 이 끝 날 때 보 냅 니 다. 보통 터미널 의 제어 프로 세 스 가 끝 날 때 같은 session
안의 각 작업 을 알 립 니 다. 이 때 는 제어 단말기 와 더 이상 연결 되 지 않 습 니 다.로그 인 Linux
시 시스템 은 로그 인 사용자 에 게 터미널 Session
을 할당 합 니 다.이 터미널 에서 실행 되 는 모든 프로그램 은 프론트 프로 세 스 그룹 과 백 엔 드 프로 세 스 그룹 을 포함 하여 일반적으로 이것 Session
에 속 합 니 다.사용자 가 로그 인 Linux
을 종료 하면 프론트 데스크 톱 프로 세 스 그룹 과 배경 에 터미널 출력 프로 세 스 가 있 습 니 다 SIGHUP
신 호 를 받 습 니 다.이 신호 의 기본 동작 은 프로 세 스 를 종료 하 는 것 입 니 다. 따라서 프론트 프로 세 스 그룹 과 백 엔 드 에 터미널 출력 이 있 는 프로 세 스 가 중 단 됩 니 다.터미널 과 관 계 를 끊 은 데 몬 에 대해 이 신 호 는 설정 파일 을 다시 읽 는 것 을 알 리 는 데 사 용 됩 니 다.bash 에서 신호 처리
bash
의 전형 적 인 응용 장면 은 내 장 된 명령 kill
을 통 해 지정 한 프로 세 스에 신 호 를 보 내 고 기본 값 으로 SIGTERM
신 호 를 보 내 는 것 입 니 다. 예 를 들 어 모든 이름 chrome
의 프로 세 스 를 종료 합 니 다.> kill `pgrep chrome`
> killall chrome
> kill `ps -ef | grep chrome | awk '{ print $2 }'`
> kill `pidof chrome`
그 밖 에
trap
신 호 를 포착 하여 특정한 신호 에 대한 처 리 를 실현 할 수 있 는데 그 문법 은 다음 과 같다.trap [COMMANDS] [SIGNALS]
trap
신 호 를 포착 한 후에 설 정 된 명령 을 실행 합 니 다. 이 명령 은 유효한 Linux 명령 이나 사용자 정의 함수 일 수 있 습 니 다. shell
스 크 립 트 에서 trap
종료 할 때 임시 파일 을 지 울 수 있 습 니 다. 예 를 들 어:#!/bin/bash
tempfile=$(mktemp) || exit
trap 'rm -f "$tempfile"' EXIT
또 다른 전형 적 인 용법 은 데 몬 에서 캡 처
SIGHUP
하고 프로필 을 다시 읽 는 것 입 니 다. 예 를 들 어:#!/usr/bin/bash
if [ ! -r "$1" ]; then
echo "Usage: $0 "
exit
fi
echo "PID: $$"
CONFIG=$1
read_config () {
echo "reading cfg from $CONFIG"
source "$CONFIG"
}
read_config
trap "read_config" HUP
while :
do
echo "$var"
sleep 15
done
다음 에 우 리 는 두 단말기 에서 테스트 를 진행 할 수 있다.
#
> bash remove_temp.sh ./config/cfg1
PID: 8807
reading cfg from ./config/cfg1
from cfg1
reading cfg from ./config/cfg1
after change
#
> cat > cfg1 << EOF
var="after change"
EOF
> kill -s HUP 8807
trap
명령 을 통 해 신 호 를 저장 하고 재 설정 할 수 있 습 니 다. 예 를 들 어:> trap "printf BOOM" INT
> ^CBOOM
> traps=$(trap) #
> trap INT #
> ^C
> eval $traps #
> ^CBOOM
trap
여러 개의 신 호 를 포착 하 는 것 도 지원 한다. 예 를 들 어:#!/usr/bin/bash
trap "echo Boom!" SIGINT SIGTERM
echo $PPID $$
while : #
do
sleep 60
done
trap
대소 문자 에 민감 하지 않 으 며 접두사 SIG
를 무시 할 수 있 습 니 다. 아래 의 표기 법 은 등가 입 니 다.trap "echo 123" SIGINT
trap "echo 123" INT
trap "echo 123" 2
trap "echo 123" int
trap "echo 123" Int
특수 한 상황
bash
외부 명령 을 수행 할 때 프론트 데스크 톱 임무 의 신호 처리 우선 순 위 를 높 일 수 있 습 니 다. 현재 데스크 톱 임무 가 수행 되 거나 중지 되 었 을 때 bash
방금 받 은 신 호 를 처리 할 수 있 습 니 다. 다음 과 같 습 니 다.#
> sleep 100 #
# ...
> # 100
#
#
> pstree -ap 16003
bash,16003
`-sleep,17249 100 #
> kill -s INT 16003 # bash
그러나 주의해 야 할 것 은
shell
에서 사용 Ctrl + C
하면 전체 프로 세 스 그룹 에 SIGINT
을 보 낼 수 있 기 때문에 상례 에서 터미널 1 에서 사용 Ctrl + C
하면 sleep
즉시 종료 되 고 빈 줄 을 인쇄 할 수 있 습 니 다. 또한 프론트 데스크 톱 임 무 를 백 스테이지 에 놓 아서 bash
신 호 를 우선 처리 할 수 있 습 니 다. 그러나 bash
종료 할 때 완성 되 지 않 은 백 스테이지 임무 가 있 으 면이 작업 들 은 고아 프로 세 스 로 변 하고 부모 프로 세 스 는 PID=1
프로 세 스 로 변 합 니 다.> (sleep 50 & sleep 50 & wait)
#
bash,15158
`-bash,7629
|-sleep,7630 50
`-sleep,7631 50
> kill 7629
#
bash,15158
> ps -ef | grep "sleep 50"
remilia 11168 1 0 16:56 pts/2 00:00:00 sleep 50
remilia 11169 1 0 16:56 pts/2 00:00:00 sleep 50
# PPID, 1
프로 세 스 가 종료 되 었 을 때 배경 작업 도 종료 하려 면 배경 작업
init
을 기록 하고 종료 하기 전에 이 프로 세 스 PID
를 종료 해 야 합 니 다.#!/usr/bin/bash
BPIDARRAY=()
for i in {0..9}; do
sleep 20 &
BPIDARRAY[$i]=$!
done
sleep 3
trap "kill `echo ${BPIDARRAY[@]}`" EXIT
wait
기타 용법
kill
정 의 된 신호 명 이나 수 치 를 포착 할 수 있 을 뿐만 아니 라 다음 과 같은 용법 도 지원 한다.trap
:
와 유사 하여 현재 시스템 이 지원 하 는 모든 신 호 를 표시 합 니 다. trap -l
또는 kill -l
: trap 을 통 해 설 치 된 신호 처리 명령 을 보 여 줍 니 다. > trap -p
trap -- 'code' EXIT
trap -- 'echo SIGINT' SIGINT
trap -p
: trap
에서 만 사용 할 수 있 는 번호 trap "some code" EXIT
의 특수 신 호 는 shell
에서 모든 탈퇴 상황 을 대표 하고 표준 0
에 서 는 포착 bash
에 사용 된다. > trap "code" EXIT
> ^D # vscode
shell
: 오류 가 발생 한 명령 을 캡 처 하고 명령 실행 에 오류 가 발생 했 을 때 미리 정 의 된 코드 블록 을 실행 합 니 다. exit
: 디 버 깅 모드 로 명령 을 실행 할 때 각 명령 이 실행 되 기 전에 미리 정 의 된 코드 블록 을 실행 합 니 다. trap "some code" ERR
설정 은 현재 프로 세 스에 만 적 용 됩 니 다. 따라서 trap "some code" DEBUG
또는 trap
을 통 해 실 행 된 스 크 립 트 를 제외 하고 .
현재 source
설정 을 계승 하지 않 습 니 다 child shell
.> trap "printf book" 2
> ^Cbook
> bash -c "trap -p" #
> bash
> ^C #
함수 에 설 치 된
shell
도 전역 적 으로 유효 합 니 다. 같은 신 호 를 중복 설정 하면 마지막 trap
만 유효 합 니 다. 특히 주의해 야 할 것 은 trap
스 크 립 트 나 비 상호작용 trap
에서 캡 처 bash
와 bash shell
할 때 다음 과 같은 방식 으로 하 는 것 이 좋 습 니 다.trap 'rm -f "$tempfile"; trap - INT; kill -s INT "$$"' INT
SIGINT
종료 신 호 를 받 을 때 SIGQUIT
원칙 에 따라 처리 하고 bash
을 누 를 때 현재 프로 세 스 팀 은 WCE (wait and cooperative exit)
을 받 습 니 다. 그러면 다음 과 같은 몇 가지 상황 이 있 습 니 다 (신 호 를 무시 하 는 상황 을 고려 하지 않 습 니 다).Ctrl + C
:SIGINT
을 처리 하면 부모 SIGINT
(호출 자) 는 하위 프로 세 스 가 신 호 를 통 해 비정 상 으로 종료 되 는 것 을 받 고 현재 스 크 립 트 를 즉시 종료 합 니 다. kill
정상적으로 종료 하면 부모 bash
(호출 자) 는 하위 프로 세 스 가 정상적으로 실행 되 었 다 고 생각 하고 스 크 립 트 를 계속 설명 합 니 다. exit
: 이 경우 신 호 를 처리 하고 자신 bash
과 비슷 합 니 다. 부모 SIGINT
(호출 자) 는 현재 스 크 립 트 를 즉시 종료 합 니 다. > cat ping_loop.sh
for i in `seq 254`; do
ping -c 2 "192.168.1.$i"
done
> bash ping_loop.sh
# , 254 Ctrl + C
# bash
상례 에서
kill
를 누 르 면 bash
먼저 Ctrl + C
를 받 고 처리 한 다음 에 정상적으로 탈퇴 한다. 그 다음 에 ping
도 SIGINT
와 이전 명령 bash
의 탈퇴 상 태 를 받 고 정상 적 인 탈퇴 를 발견 하면 그 다음 명령 을 계속 설명 한다. SIGINT
이러한 ping 192.168.0.1
신호 에 대해 기본 적 으로 처리 하 라 는 명령 은 상황 이 완전히 다르다.> cat sleep_loop.sh
i=1
while [ "$i" -le 100 ]; do
printf "%d " "$i"
i=$((i+1))
sleep 10
done
echo
> bash sleep_loop.sh
# , Ctrl + C
상례 에서
sleep
를 누 르 면 SIGINT
먼저 Ctrl + C
를 받 고 기본 적 인 방식 으로 처리 한 다음 에 sleep
도 SIGINT
와 이전 명령 bash
의 탈퇴 상 태 를 받 게 되 고 SIGINT
비정 상 탈퇴 를 발견 하면 sleep 10
즉시 탈퇴 할 수 있 습 니 다. 우 리 는 더욱 간단 한 명령 을 통 해 이해 할 수 있 습 니 다.> (ping 192.168.0.1; ping 192.168.0.2)
bash,7744
`-bash,24002
`-ping,24011 192.168.0.1
> kill -2 24011 24002 #
# ping SIGINT 0,
# bash 24002 ping 24026
#
bash,7744
`-bash,24002
`-ping,24026 192.168.0.2
> (sleep 50; sleep 50)
bash,7744
`-bash,26053
`-sleep,26054 50
> kill -2 26054 26053
# sleep SIGINT
# bash 26053 SIGINT
# bash 26053
참고 내용
Signal Trap How "Exit Traps" Can Make Your Bash Scripts Way More Robust And Reliable
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
ZSH에서 물고기까지ZSH는 수년 동안 내 기본 셸이었습니다. 이제 몇 달 동안 사용하면서 ZSH 구성에 대해 몇 가지 사항을 발견했습니다. 우리는 을 제공하는 시스템과 더 빨리 상호 작용하는 경향이 있습니다. 내.zshrc 구성에는 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.