Linux를 부팅하고 작은 Bash 스크립트를 실행하는 Live CD가 있습니다. 스크립트는 두 번째 프로그램(보통 컴파일된 C++ 바이너리)을 검색하고 실행합니다.
Ctrl+를 눌러 두 번째 프로그램을 중단 할 수 있어야 합니다 C. 무엇~해야 한다두 번째 프로그램이 중지되고 Bash 스크립트가 계속해서 정리를 실행합니다. 무엇실제로그러면 기본 애플리케이션과 Bash 스크립트가 모두 종료됩니다. 이것은 문제입니다.
trap
그래서 내장 명령을 사용하여 Bash에게 SIGINT를 무시하도록 지시합니다. 이제 Ctrl+는 CC++ 애플리케이션을 종료하지만 Bash는 계속 실행됩니다. 엄청난.
아, 예... 때로는 "두 번째 응용 프로그램"이 또 다른 Bash 스크립트인 경우도 있습니다. 그리고저것케이스, Ctrl+ C지금 하세요전혀 아무것도.
Ctrl분명히 이것이 어떻게 작동하는지에 대한 나의 이해가 잘못되었습니다 ... 사용자가 +를 누를 때 SIGINT를 얻는 프로세스를 어떻게 제어합니까 C? 이 신호를 다음으로 보내고 싶습니다.특정 프로세스.
답변1
몇 시간 동안 인터넷 검색을 한 끝에 답을 찾았습니다.
리눅스에는 개념이 있다프로세스 그룹.
TTY 드라이버에는 포그라운드 프로세스 그룹이라는 개념이 있습니다.
Ctrl+를 누르면 CTTY가
SIGINT
다음으로 전송됩니다.모든 과정포그라운드 프로세스 그룹에 있습니다. (당신은 또한 볼 수 있습니다이 블로그 항목.)
그렇기 때문에 컴파일된 바이너리가그리고이를 시작하는 스크립트가 모두 손상되었습니다. 사실 저는 메인 애플리케이션이 이 신호를 수신하기를 원합니다.아니요스크립트를 시작합니다.
이제 해결책은 분명합니다. 애플리케이션을 새 프로세스 그룹에 넣고 이 TTY의 포그라운드 프로세스 그룹으로 만들어야 합니다. 분명히 이 작업을 수행하는 명령은 다음과 같습니다.
setsid -c <applcation>
그게 다야. 이제 사용자가 Ctrl+ 를 누르면 CSIGINT가 애플리케이션(및 하위 애플리케이션에 있을 수 있음)으로 전송되며 다른 사람에게는 전송되지 않습니다. 이것이 내가 원하는거야.
setsid
자체적으로 애플리케이션을 새로운 프로세스 그룹(실제로는 완전히 새로운 "세션", 분명히 프로세스 그룹 세트)에 넣습니다.이
-c
플래그를 추가하면 이 새 프로세스 그룹이 현재 TTY에 대한 "전경" 프로세스 그룹이 됩니다. (즉, +를SIGINT
누르면 Ctrl나타납니다 C)
나는 Bash가 새로운 프로세스 그룹에서 프로세스를 실행하거나 실행하지 않는 시기에 대해 많은 상충되는 정보를 보았습니다. (특히 "대화형" 쉘과 "비대화형" 쉘 사이에는 차이가 있는 것 같습니다.) 저는 여러분이 사용할 수 있는 몇 가지 제안을 보았습니다.영리한 배관 트릭... 모르겠어요. 하지만 위의 방법이 저에게는 맞는 것 같습니다.
답변2
시작 bash 스크립트에서.
두 번째 프로그램의 PID 추적
캡처 신호
SIGINT를 포착하면 SIGINT를 두 번째 프로그램 PID로 보냅니다.
답변3
f01의 설명에서 언급했듯이 SIGTERM을 하위 프로세스로 보내야 합니다. 다음은 ^C를 캡처하고 하위 프로세스에 신호를 보내는 방법을 보여주는 몇 가지 스크립트입니다.
첫 번째는 부모님입니다.
트랩 테스트
#!/bin/bash
# trap test
# Written by PM 2Ring 2014.10.23
myname=$(basename "$0")
child=sleeploop
set_trap()
{
sig=$1
msg="echo -e \"\n$myname received ^C, sending $sig to $child, $pid\""
trap "$msg; kill -s $sig $pid" SIGINT
}
trap "echo \"bye from $myname\"" EXIT
echo "running $child..."
./$child 5 &
pid=$!
# set_trap SIGINT
set_trap SIGTERM
echo "$child pid = $pid"
wait $pid
echo "$myname finished waiting"
그리고 이제, 꼬마야.
수면주기
#!/bin/bash
# child script for traptest
# Written by PM 2Ring 2014.10.23
myname=$(basename "$0")
delay="$1"
set_trap()
{
sig=$1
trap "echo -e '\n$myname received $sig signal';exit 0" $sig
}
trap "echo \"bye from $myname\"" EXIT
set_trap SIGTERM
set_trap SIGINT
#Select sleep mode
if false
then
echo "Using foreground sleep"
Sleep()
{
sleep $delay
}
else
echo "Using background sleep"
Sleep()
{
sleep "$delay" &
wait $!
}
fi
#Time to snooze :)
for ((i=0; i<5; i++));
do
echo "$i: sleeping for $delay"
Sleep
done
echo "$myname terminated normally"
Traptest가 SIGTERM을 보내면 모든 것이 정상적으로 작동하지만, Traptest가 SIGINT를 보내면 sleeploop는 이를 전혀 보지 못합니다.
sleeploop가 SIGTERM을 포착하고 절전 모드가 포그라운드인 경우 현재 절전 모드에서 깨어날 때까지 해당 신호에 응답할 수 없습니다. 하지만 절전 모드가 배경이면 즉시 반응합니다.