STDIN이 열려 있는지 주기적으로 확인하는 방법은 무엇입니까?

STDIN이 열려 있는지 주기적으로 확인하는 방법은 무엇입니까?

일부 프로그램은 STDIN닫힐 때 종료됩니다. "포트"를 통해 Erlang/Elixir 감독 하에 이 일을 잘 수행하는 사람들.

그렇지 않은 사람들을 위해,엘릭서 문서다음 래퍼 스크립트를 제안하세요.

#!/bin/bash
# wrapper.sh
"$@" &
pid=$!
while read line ; do
  :
done
kill -KILL $pid

이를 통해 wrapper.sh my_script arg1 arg2. 을 호출 wrapper.sh하면 지정된 프로그램을 시작하고 백그라운드로 실행할 수 있으며 wrapper.shs가 STDIN닫히면 차단이 read종료되고 백그라운드 프로세스가 종료됩니다.

그러나 이 접근 방식에는 다음과 같은 단점이 있습니다.다른 이유로 백그라운드 프로세스가 종료된 경우에는 wrapper.sh알림이 표시되지 않습니다.이므로 Erlang/Elixir에도 없습니다.

이 스크립트를 수정하여 다음을 수행하고 싶습니다.

루프에서:

  • STDIN닫혀 있으면 죽여라$pid
  • 죽으면 $pid퇴출
  • 그렇지 않으면 잠시 잠을 자세요.

누구든지 이 작업을 수행하는 방법을 제안할 수 있습니까?

답변1

$pid다음과 같이 죽었는지 확인할 수 있습니다 .

while kill -0 $pid >/dev/null; do
    # $pid is still alive
done

# $pid is dead or you lack permissions to send signals to it

답변2

쉘이 dash/ busybox또는 인 ksh93경우 zsh다음에 트랩을 설정할 수 있습니다 SIGCHLD.

#! /bin/sh
trap exit CHLD
"$@" &
while read line; do :; done
kill $!
wait

"$@" &프로세스가 종료 read되거나 EOF.

하지만 귀찮은 내장 기능이 bash하나 있는데 , 바로read재시작신호로 인해 중단될 경우 더 큰 용량이 필요했습니다. 종료 시 백그라운드 프로세스가 상위 프로세스에 종료 신호를 보내도록 준비할 수 있습니다.

#! /bin/sh
{ "$@"; kill $$; } &
while read line; do :; done
pkill -P $!
kill $!
wait

명령이 더 이상 참조되지 않고 상위 프로세스가 참조 되므로 "$@"명령을 기다리고 -P(상위 pid) 선택기를 사용하는 다른 프로세스를 낭비해야 합니다 . 내장되어 있는 경우에도 여전히 추가 기능이 필요합니다. 스크립트에는 작업 제어가 없습니다. 모든 프로세스(로 시작된 프로세스 포함 )는 동일한 프로세스 그룹에서 실행됩니다.pkill$!"$@"kill $!"$@"&

p/kill -KILL신호가 충분 하지 않으면 TERM어디서나 사용할 수 있습니다.

최신(>= 4.0) 버전의 bash에서만 작동하는 또 다른 좀 더 투박한 해결 방법은 비표준 -t(timeout) 옵션을 사용하고 timeout이 1을 반환하고 status > 128이라는 사실을 활용하는 것입니다 read.readEOF

#! /bin/bash
"$@" &
while :; do
        read -t 1 line
        case $? in
        0)      ;;
        1)      kill $!; wait; exit;;
        *)      kill -0 $! || exit;;
        esac
done 2>/dev/null

이것도 마찬가지로 적용되는 것 같습니다 mksh.

관련 정보