2009-02-07 3 views
3

특정 조건에서 - 특히 특정 파일을 만든 후 Cygwin bash 스크립트를보고 종료해야합니다. 그러나 Ctrl + C와 같은 수준의 완성도로 스크립트를 정확히 종료하는 방법을 파악하는 데 어려움을 겪고 있습니다.bash 스크립트에서 Cygwin bash에서 스크립트의 프로세스 트리를 종료하는 방법

다음은 종료 될 때까지 기다리지 않는 간단한 스크립트 (test1)입니다.

#!/bin/bash 

test -f kill_me && rm kill_me 

touch kill_me 
tail -f kill_me 

이 스크립트가 포 그라운드에서 실행되는 경우, Ctrl + C가 종료됩니다 모두 tail하고 스크립트 자체. 스크립트가 백그라운드에서 실행되는 경우 kill %1 (작업 1이라고 가정)은 tail과 스크립트를 모두 종료합니다.

그러나 스크립트에서 똑같은 작업을 시도하면 이 부모로부터 연결이 끊어진 상태에서 중단되는 동안 스크립트를 실행하는 bash 프로세스 만 종료됩니다. 여기에 내가 시도 한 가지 방법 (test2)의 :이 실행되면

#!/bin/bash 

test -f kill_me && rm kill_me 

(
    touch kill_me 
    tail -f kill_me 
) & 

while true; do 
    sleep 1 
    test -f kill_me && { 
     kill %1 
     exit 
    } 
done 

, bash는 백그라운드에서 실행 서브 쉘 확인을 종료하지만, tail은 여전히 ​​주위에 달려 있습니다.

내가 명시 적으로 별도의 스크립트를 사용하는 경우, 다음과 같이 여전히 (test3) 작동하지 않습니다이 스크립트가 실행 된 후

#!/bin/bash 

test -f kill_me && rm kill_me 

# assuming test1 above is included in the same directory 
./test1 & 

while true; do 
    sleep 1 
    test -f kill_me && { 
     kill %1 
     exit 
    } 
done 

tail

은 여전히 ​​주위에 걸려있다.

내 실제 사례에서 파일을 만드는 프로세스는 특별히 쓸모가 없으므로 자체적으로 종료 할 수 없습니다. 특정 파일을 만든시기를 알아내어 그 시점에서 끝낼 수 있음을 알 수 있습니다. 불행히도, 여러 개의 인스턴스가 실행될 수 있으므로 간단하게 killall 또는 이와 동등한 것을 사용할 수 없으며 특정 인스턴스 만 죽이고 싶습니다.

답변

6

/bin/kill (bash 내장이 아닌 프로그램)은 음수 PID를 "모든 프로세스를 종료하십시오"로 해석하여 모든 하위 항목도 가져옵니다.

kill %1 

나를 위해 작품

/bin/kill -- -$$ 

에 변경.

+0

감사합니다. 그것은 Cygwin kill 맨 페이지에 문서화되어 있지 않은 것은 이상한 일입니다. 그러나 Cygwin 버전의 kill으로 작동합니다. –

1

This script는 일을 할 것 같습니다

#!/bin/bash 
# Author: Sunil Alankar 

## 
# recursive kill. kills the process tree down from the specified pid 
# 

# foreach child of pid, recursive call dokill 
dokill() { 
    local pid=$1 
    local itsparent="" 
    local aprocess="" 
    local x="" 
    # next line is a single line 
    for x in `/bin/ps -f | sed -e '/UID/d;s/[a-zA-Z0-9_-]\{1,\} 
\{1,\}\([0-9]\{1,\}\) \{1,\}\([0-9]\{1,\}\) .*/\1 \2/g'` 
    do 
     if [ "$aprocess" = "" ]; then 
      aprocess=$x 
      itsparent="" 
      continue 
     else 
      itsparent=$x 
      if [ "$itsparent" = "$pid" ]; then 
       dokill $aprocess 
      fi 
      aprocess="" 
     fi 
    done 
    echo "killing $1" 
    kill -9 $1 > /dev/null 2>&1 
} 

case $# in 
1) PID=$1 
     ;; 
*) echo "usage: rekill <top pid to kill>"; 
     exit 1; 
     ;; 
esac 

dokill $PID 
+0

스크립트가 Cygwin에서 변경되지 않았지만 시작점이었습니다. Upvoted,하지만 내 자신의 대답에 근무 스크립트. –

2

아담의 링크가 약간의주의 사항이없는 것은 아니다 불구하고, 문제를 해결하는 방향으로 날을 넣어.

스크립트는 Cygwin에서 수정되지 않은 상태로 작동하지 않으므로 다시 작성하고 몇 가지 옵션이 추가되었습니다.

#!/bin/bash 

function usage 
{ 
    echo "usage: $(basename $0) [-c] [-<sigspec>] <pid>..." 
    echo "Recursively kill the process tree(s) rooted by <pid>." 
    echo "Options:" 
    echo " -c  Only kill children; don't kill root" 
    echo " <sigspec> Arbitrary argument to pass to kill, expected to be signal specification" 
    exit 1 
} 

kill_parent=1 
sig_spec=-9 

function do_kill # <pid>... 
{ 
    kill "$sig_spec" "[email protected]" 
} 

function kill_children # pid 
{ 
    local target=$1 
    local pid= 
    local ppid= 
    local i 
    # Returns alternating ids: first is pid, second is parent 
    for i in $(ps -f | tail +2 | cut -b 10-24); do 
     if [ ! -n "$pid" ]; then 
      # first in pair 
      pid=$i 
     else 
      # second in pair 
      ppid=$i 
      ((ppid == target && pid != $$)) && { 
       kill_children $pid 
       do_kill $pid 
      } 
      # reset pid for next pair 
      pid= 
     fi 
    done 

} 

test -n "$1" || usage 

while [ -n "$1" ]; do 
    case "$1" in 
     -c) 
      kill_parent=0 
      ;; 

     -*) 
      sig_spec="$1" 
      ;; 

     *) 
      kill_children $1 
      ((kill_parent)) && do_kill $1 
      ;; 
    esac 
    shift 
done 

유일한 단점은 그것이 치명적인 신호, 즉 "종료", "사망"또는 "중단 된"(당신이 보내는 내용에 따라)를 수신 할 때 인쇄를 비난 다소 추한 메시지는 다음과 같습니다 여기 내 버전입니다 . 그러나, 나는 배치 스크립트로 그것으로 살 수있다.

관련 문제