배경

배경

배경

나는 기사를 읽었다우편 엽서신호 처리와 관련하여 SIGINT대화형 및 비대화형 쉘 모두에서 선택하고 사용할 코드에서 신호를 올바르게 처리하는 방법을 여전히 이해하지 못합니다.

제 스크립트의 간단한 예를 들어보고 특정 부분에 대해 질문하겠습니다.


어디서나 구하고 사용할 수 있는 유용한 기능을 갖춘 스크립트가 있습니다.

/tmp/useful_functions.sh

#!/bin/bash

function example()
{
    echo "Main script started"

    # Make process run forever in the background.
    ( while sleep 1; do echo "Background script running"; done ) &

    # Make subshell work for 10 seconds.
    local output="$(sleep 10; echo "Subshell completed")"
    echo "${output}"

    # Kill the backgrounded process once the subshell has finished.
    { kill "${!}" && wait "${!}"; } &> /dev/null

    echo "Main script completed"
}

테스트 1

사용하자다른 스크립트 내에서 실행하세요.

/tmp/test.sh

#!/bin/bash

source /tmp/useful_functions.sh

example

이제 서브쉘이 작동하는 동안 실행 /tmp/test.sh하고 눌러 보겠습니다. (서브쉘 = )Control-C
$(sleep 10; echo "Subshell completed")

왜냐하면. . . 결과Test 1

/tmp/test.sh, example, subshell프로세스 background가 종료되었습니다.
프롬프트가 새로운 입력을 기다리고 있습니다.

질문

  1. SIGINT프로세스 간 전송/처리/전파 순서는 무엇입니까?
    (멘션은 SIGINT다음 주소로 보내야 합니다.모든 잠재 고객가장 안쪽 프로세스가 먼저 처리해야 합니다. )
  2. 백그라운드 프로세스가 종료되는 이유는 무엇입니까?

테스트 2

사용하자대화형 Bash에서 직접 실행:

...$ source /tmp/useful_functions.sh
...$ example

Control-C서브쉘이 작동하면 다시 누르십시오.
(서브쉘 = $(sleep 10; echo "Subshell completed"))

왜냐하면. . . 결과Test 2

example프로세스가 subshell종료되었지만 backgrounded프로세스는 활성 상태로 유지됩니다. 프로세스의 출력이 인쇄되더라도
프롬프트는 여전히 새로운 입력을 기다리고 있습니다.backgrounded

질문

  1. SIGINT프로세스 간 전송/처리/전파 순서는 무엇입니까?
  2. 백그라운드 프로세스가 지금 종료되지 않는 이유는 무엇입니까?

개선된 예

동작을 완전히 이해하지는 못하지만 Test 1이 동작은 제가 기대하는 동작이며 대화형 Bash를 통해 이를 달성하고 싶습니다.
백그라운드 프로세스와 기존 서브셸을 감싸는 또 다른 서브셸을 만들고, 새 프로세스가 종료되면 백그라운드 프로세스와 기존 서브셸도 종료되기를 바라는 아이디어입니다.

/tmp/useful_functions.sh

#!/bin/bash

function example()
{
    (
        echo "Main script started"

        # Make process run forever in the background.
        ( while sleep 1; do echo "Background script running"; done ) &

        # Make subshell work for 10 seconds.
        local output="$(sleep 10; echo "Subshell completed")"
        echo "${output}"

        # Kill the backgrounded process once the subshell has finished.
        { kill "${!}" && wait "${!}"; } &> /dev/null

        echo "Main script completed"
    )
}

중복된 결과Test 1

/tmp/test.sh, example및 프로세스가 outer subshell종료 되었습니다. 프롬프트가 새로운 입력을 기다리고 있습니다.inner subshellbackground

질문

  1. SIGINT프로세스 간 전송/처리/전파 순서는 무엇입니까?
  2. 백그라운드 프로세스가 종료되는 이유는 무엇입니까?

중복된 결과Test 2

example, outer subshell, inner subshell프로세스 background가 종료되었습니다.
프롬프트가 새로운 입력을 기다리고 있습니다.

질문

  1. SIGINT프로세스 간 전송/처리/전파 순서는 무엇입니까?
  2. 백그라운드 프로세스가 종료되는 이유는 무엇입니까?

질문

SIGINT이 시점에서 저는 실제로 백그라운드 프로세스 후에 정리 작업을 해야 한다는 것과 이를 처리할 어딘가에 캡처해야 한다는 것을 깨달았습니다 .

해결책

나는 Bash에서 일반적으로 처리 및 전파가 어떻게 수행되는지 모르기 때문에 SIGINT지식에 근거한 추측을 했고 효과가 있을 것이라고 생각했지만 확실하지 않은 솔루션을 생각해냈습니다.

#!/bin/bash

function example()
{
    (
        echo "Main script started"

        # Make process run forever in the background.
        (
            trap "echo Cleanup; trap - SIGINT; kill -s SIGINT ${$}" SIGINT
            while sleep 1; do echo "Background script running"; done
        ) &

        # Make subshell work for 10 seconds.
        local output="$(sleep 10; echo "Subshell completed")"
        echo "${output}"

        # Kill the backgrounded process once the subshell has finished.
        { kill "${!}" && wait "${!}"; } &> /dev/null

        echo "Main script completed"
    )
}

질문

  1. 내 트랩이 올바르게 처리/전파됩니까 SIGINT?
  2. 이것이 ${$}올바른 과정인가요?
    (언급된 게시물에서는 프로세스가 스스로 종료되어야 한다고 말하지만 예제에서는 ${$}이를 대신 사용합니다 ${BASHPID}.)

관련 정보