[Linux 셸 스크립트] 셸 기능 다루기 - 087 스크립트 실행할 때 시그널을 받아서 현재 실행 상태 출력하기
본문 바로가기
IT 이야기/Linux 셸 스크립트

[Linux 셸 스크립트] 셸 기능 다루기 - 087 스크립트 실행할 때 시그널을 받아서 현재 실행 상태 출력하기

by 찬찬이 아빠 2021. 4. 13.
반응형
  1. 사용 명령어

(1) trap

(2) nc

(3) sleep

 

 

  2. 키워드 & 사용처

(1) 키워드

시그널, 끼어들기, 트랩

 

(2) 사용처

처리 시간이 긴 셸 스크립트를 실행하는데 프로세스를 정지하지 않고 내부 실행 상태를 표시하고 싶을 때 사용합니다.

 

  3. 실행 예제
$ ./sig-usr1.sh
Connection to 192.168.2.105 80 port [tcp/http] succeeded!
Connection to 192.168.2.105 80 port [tcp/http] succeeded!
Connection to 192.168.2.105 80 port [tcp/http] succeeded!
Try Count: 3        <- 다른 터미널에서 시그널을 보내면 현재 Try Count를 표시 가능
Connection to 192.168.2.105 80 port [tcp/http] succeeded!
... 생략 ...

 

 

  4. 스크립트

#!/bin/sh

 

# 실행 횟수

count=0         

 

#통신 대상 서버

server="192.168.2.105"         

 

# 시그널 USR1 트랩 설정. 현재 $count 표시

trap 'echo "Try Count: $count"' USR1       

 

# nc 명령어로 연속 통신 확인 반복

while [ $count" -le 1000 ]           

do

    # 카운터 1 늘리고 nc 명령어 실행

    # 마지막에 1초 대기

    count=$(expr $count + 1)       

    nc -zv "$server" 80     

    sleep 1     

done

 

 

  5. 해설

이 스크립트는 반복 처리를 하여 통신 시간이 긴 스크립트가 실행 중일 때 해당 프로세스에 kill 명령어로 USR1 시그널으르 보내서 지금까지 반복한 실행 횟수를 표시합니다. 여기서는 nc 명령어를 사용해 TCP 포트 80(http)으로 보내는데 지금까지 반복한 횟수를 "Try Count:"로 표시합니다. 에제에서 사용하는 nc 명령어는 서버와의 통신을 확인하는데 유용합니다.

 

실행 중인 프로세스 상태를 알려면 프로세스에 시그널을 보내고 그때의 내부 상태를 표시하는 방법이 있습니다. 셸 스크립트에서 이런 시그널 처리를 하려면 trap 명령어를 사용합니다.

 

예제에서 사용하는 USR1 시그널은 애플리케이션마다 원하는 대로 기능을 지정하는 시그널입니다. 예를 들어 웹 서버로 자주 쓴ㄴ 아파치 httpd에 USR1 시그널이 오면 graceful 모드로 '자연스럽게 재기동'을 하고 리눅스 dd 명령어에 USR1 시그널을 보내면 명령어를 계속 실행하면서 '지금까지 처리한 블록 수'를 표시합니다.

 

이런 구조를 셸 스크립트에서도 구현하면 처리 시간이 오래 걸리는 스크립트라도 현재 실행 중인 상태를 볼 수 있어서 편리합니다. 예제에서는 nc 명령어 반복 ㄹ횟수를 표시하고 있습니다.

 

우선 과 에서 확인 횟수 카운터를 초기화하고 대상 서버를 정의합니다. 셸 변수 count가 실행 반복 횟수가 됩니다.

 

은 시그널을 수신했을 때 어떤 처리를 할지 작성한 부분입니다. trap 명령어오 USR1 시그널을 받으면 "Try Count: $count"를 echo 명령어로 표시해서 지금까지 처리한 반복 횟수를 표시합니다. 부분은 스크립트를 위에서부터 순서대로 실행할 때는 아무것도 표시하지 않습니다. 실행 중에 실제로 USR1 시그널이 왔을 때 이 처리를 하도록 정의한 문자이라고 이해하기 바랍니다. 이렇게 셸 스크립트에서는 trap 명령어를 사용해서 끼어들기 처리를 작성할 수 있습니다.

 

에서 while 문으로 통신 확인(실행 시간이 긴 처리)을 합니다. 카운터를 1 늘려가며 1000번 실행합니다. 에서 nc 명령어로 대상 서버 80번(http)로 통신 확인을 하고 sleep 명령어로 1초씩 기다린 다음 expr 명령어로 셸 변수 count 값을 1 늘립니다.

 

실제로 이 프로세스에 USR1 시그널을 보내려면 스크립트를 실행시킨 채 다른 터미널에서 실행 중인 프로세스 목록을 표시하는 ps 명령어를 실행합니다.

$ ps x
PID	TT	STAT	TIME	COMMAND
264	??	S	0:19.49	/usr/libexe/UserEventAgent (Aqua)
266	??	S	33:12.42 /usr/sbin/distnoted agent
267	??	S	0:11.10	/usr/sbin/universalaccessd launchd -s
29321	pts/1	S+	0:00.00	/bin/sh ./sig-usr1.sh

PID 열을 보면 sig-usr1.sh를 실행하는 프로세스 ID가 29321입니다. 이 프로세스 ID에 kill 명령어로 USR1 시그널을 보냅니다.

$ kill -s USR1 29321

이렇게 명령어를 실행하면 스크립트에서 USR1 시그널을 수신해서 실행 예제(sig-usr1.sh)에서 본 것 처럼 "Try Count: 3"같이 nc 명령어 실행 횟수를 표시합니다.

 

 

<주의사항>

OS에 따라서 사용 가능한 시그널은 조금씩 다릅니다. 사용 가능한 시그널은 kill -l로 확인할 수 있습니다. 이때 표시되는 시그널은 모두 SIG로 시작합니다. 예를 들어 HUP 시그널은 SIGHUP으로 표시됩니다.

 

 

 

참고서적 : 유닉스 리눅스 셸 스크립트 예제 사전

반응형

댓글