sleep 명령을 실행한 후 명령 프롬프트를 종료하는 방법은 무엇입니까?

sleep 명령을 실행한 후 명령 프롬프트를 종료하는 방법은 무엇입니까?

간단한 스크립트가 있습니다.

f=1 # initial value
loop(){
...    
    if [[ $f -eq 1 ]]
    then
        echo $msg1
        f=2
        (sleep $interval; loop) &
        exit 1
    elif [[ $f -eq 2 ]]
    then
        echo $msg2
        f=1
        (sleep $interval; loop) &
        exit 2
    fi
...
}

그 목적은 이 두 메시지 사이를 차례로 반복하는 것입니다. 나는 스크립트가 백그라운드에 있기를 원하기 때문에 일반적인 while 루프 대신 이 작업을 수행하고 있습니다. 따라서 내 터미널에서 일어날 것으로 예상되는 작업은 다음과 같습니다.

gt@gt:~./timer.sh
<msg1>
gt@gt:~<me running some other commands>
<some output>
gt@gt:~<as soon as $interval time gets over>
<msg2>
gt@gt:~<fresh prompt>

보시다시피, 일반 에코 출력이 나타나는 위치에 msg2가 나타나기를 원하며 그 직후에 새 명령 입력 프롬프트를 남겨 두어야 합니다. 그러나 실제로 일어나는 일은 다음과 같습니다.

gt@gt:~./timer.sh
<msg1>
gt@gt:~<me running some other commands>
<some output>
gt@gt:~<msg2>
<same prompt is still waiting for input here>

이 문제를 어떻게 해결하나요?

#!/bin/bash초를 실행 하고 설정하여 sleep=3이 문제를 로컬에서 확인할 수 있습니다 .

답변1

타이머 스크립트가 SIGINT상위 프로세스( $PPID)에 신호를 보내도록 하세요.

#!/bin/bash
echo "Going to interrupt $PPID in 5 seconds"
sleep 5
echo "More output"
kill -SIGINT $PPID
sleep 5

이 스크립트가 ./script &백그라운드( )에서 실행되면 출력을 전송하고 절전 모드로 전환한 다음 추가 출력을 전송하고 프롬프트를 강제로 다시 그려야 합니다.

스크립트는 다시 잠자기 상태가 된 후 종료됩니다.

OP 스크립트 업데이트

f=1 # initial value
loop(){
...    
    if [[ $f -eq 1 ]]
    then
        echo $msg1
        kill -SIGINT $PPID
        f=2
        (sleep $interval; loop) &
        exit 1
    elif [[ $f -eq 2 ]]
    then
        echo $msg2
        kill -SIGINT $PPID
        f=1
        (sleep $interval; loop) &
        exit 2
    fi
...
}

쉘 프로세스가 신호에 의해 중단되면 보류 중인 입력 행이 손실되지만 명령 프롬프트는 타이머 스크립트 출력 후에 다시 그려집니다.

편집하다

하위 스크립트에서 이 동작을 재현하려면 호출자 스크립트의 상위 PID 환경 변수를 하위 스크립트로 전달하십시오.

main.sh

...
./timer.sh $PPID
...
#exits

timer.sh

...
# Save the parent pid argument
gp=$1
...
# Replace instances of $PPID with $gp in timer.sh
...
kill -SIGINT $gp

답변2

내 생각에 다음 쉘 스크립트는timer당신이 원하는 것을 하거나 당신이 원하는 것에 가까운 것을 할 것입니다.

#!/bin/bash

interval=60  # seconds
tips="Skip waiting with Yes|Enter, exit with No|Escape"
msg1="First message ...

$tips"
msg2="Second message ...

$tips"

f=1 # initial value
while true
do
    if [[ $f -eq 1 ]]
    then
#        zenity --notification --text="$msg1" 2> /dev/null
        LANG=C zenity --question --title="${0##*/}" \
        --text="$msg1" --timeout="$interval" --width=400 2> /dev/null
    elif [[ $f -eq -1 ]]
    then
#        zenity --notification --text="$msg2" 2> /dev/null
        LANG=C zenity --question --title="${0##*/}" \
        --text="$msg2" --timeout="$interval" --width=400 2> /dev/null
    fi
    ans=$?
    if [ $ans -eq 0 ] || [ $ans -eq 5 ]
    then
     f=$((-f))
    else
      zenity --info --title="${0##*/}" \
        --text="Exiting now" --timeout="3" 2> /dev/null
     break
    fi
done & pid=$!

echo "kill with
kill $pid       # useful during testing 
--------------------------------------------"
  • 나는 사용한다zenity --question메시지가 자주 나타나지 않고 정말로 알고 싶다면 메시지를 보내십시오(그리고 아마도 이에 대해 조치를 취해야 할 수도 있습니다). 이렇게 하면 백그라운드 작업을 정상적으로 종료할 수도 있습니다.

    여기에 이미지 설명을 입력하세요.

  • 주석 해제zenity --notificationzenity --question명령에서 덜 방해적인 메시지를 원하면 명령을 주석 처리하세요.

    sleep $interval또한 각 줄 다음에 명령줄을 입력 해야 합니다 zenity --notification.

    하지만 이는 프로세스 번호를 사용하여 백그라운드 프로세스를 종료해야 함을 의미하기도 합니다.

    kill <process number>
    

    타이머 쉘 스크립트를 시작하면 실제 프로세스 번호가 표시됩니다.ps

    $ ./timer
    kill with
    kill 15585       # useful during testing 
    --------------------------------------------
    $ ps -e |grep timer
    15585 pts/3    00:00:00 timer
    

관련 정보