다음 스크립트를 고려해보세요.
#!/bin/bash
OFILE='log'
echo 'ok' > ${OFILE}
kill -SIGSTOP $$
echo 'after stop' > ${OFILE}
대화형 셸에서는 스크립트가 중지되고 출력은 ok
. 그러나 다음과 같이 시작되면
screen -d -m ./test.sh
출력은 입니다 after stop
. 화면이 신호를 처리합니까? 스크린 세션에서 프로세스를 일시 중단하는 방법은 무엇입니까?
답변1
아마도 화면 프로세스가 중지된 bash 프로세스를 다시 시작하는 중일 것입니다. 다음을 시도했습니다(두 프로세스 모두에 SIGSTOP 신호 보내기).
test.sh
#!/bin/bash
OFILE='log'
echo 'ok' > ${OFILE}
echo 'screen pid ' $(screen -list | grep sc_test | cut -f1 -d'.' | sed 's/\W//g') >> ${OFILE}
echo 'test.sh pid ' $$ >> ${OFILE}
kill -SIGSTOP $(screen -list | grep sc_test | cut -f1 -d'.' | sed 's/\W//g')
kill -SIGSTOP $$
echo 'after stop' >> ${OFILE}
화면 명령
screen -dmS sc_test ./test.sh
로그 파일
ok
screen pid 4453
test.sh pid 4454
목록 화면
screen -list
There is a screen on:
4453.sc_test (11/05/2015 10:45:20 AM) (Detached)
1 Socket in /var/run/screen/S-root.
답변2
시험GNU 화면-4.0.2의 소스 코드화면은 하위 프로세스가 중지되었는지 확인한 다음 SIGCONT를 사용하여 재개하려고 시도하는 것을 보여주었습니다. 다음은 관련 부분입니다 screen.c
.
1561 if (WIFSTOPPED(wstat))
1562 {
1563 debug3("Window %d pid %d: WIFSTOPPED (sig %d)\n", p->w_number, p->w_pid, WSTOPSIG(wstat));
....
1578 /* Try to restart process */
1579 Msg(0, "Child has been stopped, restarting.");
1580 if (killpg(p->w_pid, SIGCONT))
1581 kill(p->w_pid, SIGCONT);
1582 }
이 동작은 옵션이나 구성 파일을 통해 변경할 수 없는 것 같습니다. 화면 프로세스를 중지하기 위해 제안된 솔루션에는 바람직하지 않은 부작용이 있을 수 있습니다. 더 나은 접근 방식은 중지된 프로세스를 화면에서 숨기는 것입니다. Bash 스크립트의 경우 서브셸을 사용하여 이 작업을 수행할 수 있습니다.
#!/bin/bash
(
OFILE='log'
echo 'ok' > ${OFILE}
kill -SIGSTOP ${BASHPID}
echo 'after stop' > ${OFILE}
)
다른 쉘의 경우에는 그렇게 간단하지 않을 수 있습니다(예: tcsh의 경우).
#!/bin/tcsh
(\
set OFILE='log' ;\
echo 'ok' > ${OFILE} ;\
kill -STOP `exec sh -c 'echo ${PPID}'` ;\
echo 'after stop' > ${OFILE} \
)
주요 차이점은 서브쉘의 PID를 얻는 방법입니다. 추가 정보여기.
또는 다음을 사용하여 수정하지 않고 스크립트를 시작할 수 있습니다.싸개스크립트:
#!/bin/bash
SCRIPTDIR="$(dirname "$(readlink -f -n "$0")")"
${SCRIPTDIR}/test.sh
실행하려면:
screen -d -m ./wrapper.sh