간단한 스크립트가 있습니다.
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 --notification
zenity --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