program story

bash : 백그라운드 함수 프로세스를 조용히 종료

inputbox 2021. 1. 7. 07:55
반응형

bash : 백그라운드 함수 프로세스를 조용히 종료


쉘 전문가,

foo()지루하고 긴 명령에 대한 진행률 표시 줄을 표시하기 위해 백그라운드 함수 (예 :)를 시작하는 bash 셸 스크립트 가 있습니다.

foo()
{
    while [ 1 ]
    do
        #massively cool progress bar display code
        sleep 1
    done
}

foo &
foo_pid=$!

boring_and_long_command
kill $foo_pid >/dev/null 2>&1
sleep 10

이제 foo죽으면 다음 텍스트가 표시됩니다.

/home/user/script: line XXX: 30290 Killed                  foo

이것은 내, 그렇지 않으면 엄청나게 멋진 진행 표시 줄 디스플레이의 굉장함을 완전히 파괴합니다.

이 메시지를 어떻게 제거합니까?


kill $foo_pid
wait $foo_pid 2>/dev/null

BTW, 엄청나게 멋진 진행률 표시 줄에 대해 모르겠지만 Pipe Viewer (pv)를 보셨습니까? http://www.ivarch.com/programs/pv.shtml


이 문제를 직접 알게되었고 "거부"가 우리가 찾고있는 것임을 깨달았습니다.

foo &
foo_pid=$!
disown

boring_and_long_command
kill $foo_pid
sleep 10

프로세스가 여전히 감시 된 "작업"의 쉘 목록에 있기 때문에 사망 메시지가 인쇄됩니다. disown 명령은이 목록에서 가장 최근에 생성 된 프로세스를 제거하므로 SIGKILL (-9)을 사용해도 종료시 디버그 메시지가 생성되지 않습니다.


kill $foo_pid >/dev/null 2>&1을 다음 줄로 바꾸십시오 .

(kill $foo_pid 2>&1) >/dev/null

업데이트 :

이 답변은 @ mklement0의 의견에 설명 된 이유로 올바르지 않습니다.

이 답변이 백그라운드 작업에 효과적이지 않은 이유는 kill 명령이 완료된 후 Bash 자체가 종료 된 작업에 대한 상태 메시지를 비동기 적으로 출력하기 때문입니다. 이는 허용 된 답변에서와 같이 wait를 사용하지 않는 한 직접 억제 할 수 없습니다.


이것은 비슷한 문제에 대해 생각해 낸 해결책입니다 (장기 실행 프로세스 중에 타임 스탬프를 표시하고 싶음). 이것은 pid를 알고있는 한 조용히 서브 쉘을 죽일 수있는 killsub 함수를 구현합니다. 트랩 명령은 다음을 포함하는 것이 중요합니다. 스크립트가 중단 된 경우 서브 쉘이 계속 실행되지 않습니다.

foo()
{
    while [ 1 ]
    do
        #massively cool progress bar display code
        sleep 1
    done
}

#Kills the sub process quietly
function killsub() 
{

    kill -9 ${1} 2>/dev/null
    wait ${1} 2>/dev/null

}

foo &
foo_pid=$!

#Add a trap incase of unexpected interruptions
trap 'killsub ${foo_pid}; exit' INT TERM EXIT

boring_and_long_command

#Kill foo after finished
killsub ${foo_pid}

#Reset trap
trap - INT TERM EXIT

이 "해킹"이 작동하는 것 같습니다.

# Some trickery to hide killed message
exec 3>&2          # 3 is now a copy of 2
exec 2> /dev/null  # 2 now points to /dev/null
kill $foo_pid >/dev/null 2>&1
sleep 1            # sleep to wait for process to die
exec 2>&3          # restore stderr to saved
exec 3>&-          # close saved version

여기 에서 영감을 얻었습니다 . 세계 질서가 회복되었습니다.


함수 시작 부분에 추가 :

trap 'exit 0' TERM

이를 수행하는 또 다른 방법 :

    func_terminate_service(){

      [[ "$(pidof ${1})" ]] && killall ${1}
      sleep 2
      [[ "$(pidof ${1})" ]] && kill -9 "$(pidof ${1})" 

    }

그것을 부르다

    func_terminate_service "firefox"

작업 알림을 비활성화하는 또 다른 방법은 명령을 sh -c 'cmd &'구성에 배경 화하는 것 입니다.

#!/bin/bash

foo()
{
   while [ 1 ]
   do
       sleep 1
   done
}

#foo &
#foo_pid=$!

export -f foo
foo_pid=`sh -c 'foo & echo ${!}' | head -1`

# if shell does not support exporting functions (export -f foo)
#arg1='foo() { while [ 1 ]; do sleep 1; done; }'
#foo_pid=`sh -c 'eval "$1"; foo & echo ${!}' _ "$arg1" | head -1`


sleep 3
echo kill ${foo_pid}
kill ${foo_pid}
sleep 3
exit

그것을 set +m억제하기 위해 before를 사용할 수 있습니다 . 여기 에 대한 자세한 정보

ReferenceURL : https://stackoverflow.com/questions/5719030/bash-silently-kill-background-function-process

반응형