sh -c로 실행된 스크립트가 신호를 수신하지 않습니다.

sh -c로 실행된 스크립트가 신호를 수신하지 않습니다.

시간이 많이 걸리는 명령을 실행하기 전에 3분 동안 대기하는 스크립트가 있습니다. SIGINT장기 실행 명령을 실행할 때가 아니라 잠자기 상태에서만 수신하는 경우 스크립트를 종료하고 싶습니다 . 이는 시간이 많이 걸리는 명령의 인스턴스가 주어진 순간에 하나만 실행되도록 하기 위한 것입니다.

이것은 myscript.sh:

#!/bin/bash

trap 'exit' INT
sleep 180 &
wait
trap '' INT

# Long running command
/etc/init.d/myd sync 

실행 방법은 다음과 같습니다.

kill -INT `pgrep myscript.sh` 2>/dev/null; ! pgrep -x "myscript.sh" > /dev/null && /opt/my/scripts/myscript.sh &

이제 후속 실행에서도 예상대로 작동합니다. 즉

  1. 실행 중이 아닌 경우 스크립트를 실행합니다.

  2. SIGINT스크립트가 실행 중이지만 아직 장기 실행 명령을 실행하지 않은 경우 스크립트를 중지( send )한 다음 다시 시작하세요.

  3. 스크립트가 실행 중이고 장기 실행 명령을 실행하는 경우 아무 작업도 수행하지 않습니다.

그러나 다음을 사용하여 동일한 라이너를 실행할 때 sh -c:

sh -c 'kill -INT `pgrep myscript.sh` 2>/dev/null; ! pgrep -x "myscript.sh" > /dev/null && /opt/my/scripts/myscript.sh &'

이전에 실행된 적이 없으면 스크립트를 시작하지만 중지할 수는 없는 것 같습니다.

왜 이것이 작동하지 않는지 이해하지 못합니다.

답변1

따라서 명령 경로를 약간 수정해야 했지만 이것이 귀하의 요구 사항을 충족한다고 생각합니다. 하지만 먼저 스크립트를 수정해야 합니다.

#!/bin/bash
# Make sure we know when the trap fires. 
trap 'printf "quiting with return code %d\n" "$?"; exit' INT
sleep 180 &
wait
trap '' INT

# Long running command
/usr/bin/sleep 86400

그러면 두 번째 명령을 다음과 같이 변경하여 원하는 결과를 얻을 수 있습니다.

sh -c 'set -x; (exec kill --verbose -INT $(pgrep myscript.sh) 2>/dev/null); ! pgrep -x "myscript.sh" > /dev/null && /tmp/myscript.sh &'

이 방법으로 실행하면 예상대로 작동하는지 확인한 후 스크립트의 첫 번째 트랩에서 printf 문을 제거하고 다음과 같은 명령을 실행할 수 있습니다.

 sh -c '(exec kill -INT $(pgrep myscript.sh) 2>/dev/null); ! pgrep -x "myscript.sh" > /dev/null && /tmp/myscript.sh &'

위 명령의 첫 번째 문에 괄호가 없어 하위 쉘에서 실행되는 경우 해당 sh프로세스가 대체되고 kill두 번째 문은 실행되지 않습니다.

관련 정보