계층적 프로세스 실행 중에 SIGINT를 처리하지 못했습니다.

계층적 프로세스 실행 중에 SIGINT를 처리하지 못했습니다.

다음과 같은 프로세스 실행 구조가 있습니다.

script0.sh
    script1.sh
        script2.sh
        script3.sh

중요성:

  • script0.sh는 script1.sh를 실행합니다.
  • script1.sh는 script2.sh 및 script3.sh를 실행합니다.

이상적으로는 script1.sh에 정리 및 종료를 수행하는 트랩 핸들러를 갖고 싶습니다.
어떤 이유로 작동하지 않습니다.

또한 모든 스크립트에서 트랩 핸들러를 사용해 보았지만 script0.sh에서만 트랩 핸들러를 호출했습니다.

하위 프로세스(예: script1.sh)를 종료하기 위해 script0.sh의 트랩 핸들러를 사용해 보았지만 프로세스가 완료될 때까지 정지됩니다.

"trap -p" 명령을 사용하여 모든 스크립트에 대해 트랩 핸들러를 등록했지만 script0.sh에만 트랩 핸들러가 있음을 확인했습니다.

노트:

  • script2.sh는 실제로 "rsync"이고 나머지 스크립트는 내 것입니다.
  • script1.sh, script2.sh 및 script3.sh는 "&" 연산자를 사용하여 백그라운드로 전송됩니다.
  • 백그라운드로 전송된 각 프로세스에 대해 "대기"를 수행합니다.

이 문제를 재현하는 스크립트 파일을 만들었습니다.

스크립트0.sh:

#!/usr/bin/env bash

function cleanup_script0()
{
    echo "SIGINT in script0.sh"
    kill -s SIGINT $script1_pid
    wait $script1_pid
}

trap cleanup_script0 SIGINT

./script1.sh &
script1_pid=$!
wait $script1_pid

스크립트1.sh:

#!/usr/bin/env bash

function cleanup_script1()
{
    echo "SIGINT in script1.sh"
    kill -s SIGINT $script2_pid
    wait $script2_pid
    kill -s SIGINT $script3_pid
    wait $script3_pid
}

trap cleanup_script1 SIGINT

rsync_file_to_copy="$( mktemp )"
dd if=/dev/urandom of="$rsync_file_to_copy" bs=1M count=1
rsync --timeout=5 --bwlimit=200 "$rsync_file_to_copy" "$( mktemp -d )/" &
script2_pid=$!
wait $script2_pid
echo "Finished script2.sh"

./script3.sh
script3_pid=$!
wait $script3_pid
echo "Finished script3.sh"

Script3.sh:

#!/usr/bin/env bash

function cleanup_script3()
{
    echo "SIGINT in script3.sh"
}

trap cleanup_script3 SIGINT

delay_counter=0
while [ 8 -gt $delay_counter ]; do
    echo "script3.sh: $( date "+%H_%M_%S" )"
    let 'delay_counter++'
    sleep 1
done

위 스크립트의 실행 결과는 다음과 같습니다.

재동기화 중에 CTRL+C를 누르면 출력됩니다.

$ ./script0.sh 
1+0 records in
1+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.00604244 s, 174 MB/s
^CSIGINT in script0.sh
rsync error: received SIGINT, SIGTERM, or SIGHUP (code 20) at rsync.c(703) [sender=3.2.3]
rsync error: received SIGINT, SIGTERM, or SIGHUP (code 20) at io.c(503) [generator=3.2.3]
Finished script2.sh
script3.sh: 23_57_24
script3.sh: 23_57_25
script3.sh: 23_57_26
script3.sh: 23_57_27
script3.sh: 23_57_28
script3.sh: 23_57_29
script3.sh: 23_57_30
script3.sh: 23_57_31
Finished script3.sh

script3.sh 중에 CTRL+C를 누르면 출력됩니다.

$ ./script0.sh 
1+0 records in
1+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.00585018 s, 179 MB/s
Finished script2.sh
script3.sh: 23_57_46
script3.sh: 23_57_47
^CSIGINT in script0.sh
script3.sh: 23_57_48
script3.sh: 23_57_49
script3.sh: 23_57_50
script3.sh: 23_57_51
script3.sh: 23_57_52
script3.sh: 23_57_53
Finished script3.sh

답변1

control+를 선택 c하면 SIGINT가 전경 프로세스 그룹의 모든 구성원에게 전송됩니다(또는 신호가 전혀 전송되지 않습니다. termios매뉴얼 페이지 참조). 따라서 스크립트가 실제로 점점 더 많은 작업을 수행하더라도 프로세스 그룹으로 전송되는 신호의 일반적인 동작에 의존하여 신호 처리를 단순화할 수 있습니다.

#!/bin/sh
# script0 - apparently this script does more things that were absent
# in the question, so we run the first script instead of executing
# the next script (this changes nothing from the prior result)
./script1
echo and we do some other things here ...

그리고 script1이제 분명히 어딘가에서 일종의 출력 리디렉션이 진행되고 있으므로 이것이 상단에서 발생한다고 가정해 보겠습니다(이전 결과와 아무 것도 변경되지 않음).

#!/usr/bin/env bash
# script1 - replace rsync with a hopefully similar `sleep` call,
# plus now the output redirect, minus anything they haven't yet
# told us about

exec > >(tee and-a-ruthless-devotion-to-the-pope) 2>&1

echo RUN script2
# `command & wait;` is just a complicated and verbose way to write
# `command;` (unless there is yet another thing going on they
# haven't yet told us about??)
sleep 9

echo RUN script3
./script3

그리고script3

#!/usr/bin/env bash
delay_counter=0
while [[ 8 -gt $delay_counter ]]; do
   echo -n "script3 time "
   date +%H:%M:%S
   (( delay_counter++ ))
   sleep 1
done

이후에도 chmod +x script*여전히 원인

$ ./script0
RUN script2
^C
$ ./script0
RUN script2
RUN script3
script3 time 16:28:31
script3 time 16:28:32
script3 time 16:28:33
^C
$ 

불필요한 신호 처리는 상황을 복잡하게 만들 뿐이며, 결과적인 복잡성을 해결하려면 더 많은 복잡성이 필요합니다. 기본 동작을 단순화하고 이에 의존하지 않는 이유는 무엇입니까?

관련 정보