서브쉘을 자동으로 종료하시겠습니까?

서브쉘을 자동으로 종료하시겠습니까?

나는 이런 것을 구현하고 싶다Q/A그러나 하위 쉘의 경우. 다음은 내가 시도하는 최소한의 예입니다.

(subshell=$BASHPID
  (kill $subshell & wait $subshell 2>/dev/null) &
sleep 600)

echo subshell done

subshell done다음 대신 반환 만 가능하도록 하려면 어떻게 해야 합니까 ?

./test.sh: line 4:  5439 Terminated              ( subshell=$BASHPID; ( kill $subshell && wait $subshell 2> /dev/null ) & sleep 600 )
subshell done

편집: 여기서 용어가 틀렸을 수 있습니다. 서브쉘이란 첫 번째 괄호 세트 내의 프로세스를 의미합니다.

업데이트:

상황에 맞게 실제 프로그램의 스니펫을 게시하고 싶습니다. 위의 내용을 단순화하면 다음과 같습니다.

# If subshell below if killed or returns error connected variable won't be set
(if [ -n "$2" ];then

      # code to setup wpa configurations here

      # If wifi key is wrong kill subshell
      subshell=$BASHPID
      (sudo stdbuf -o0 wpa_supplicant -Dwext -i$wifi -c/etc/wpa_supplicant/wpa_supplicant.conf 2>&1 \
        | grep -m 1 "pre-shared key may be incorrect" \
        && kill -s PIPE "$subshell") &

      # More code which does the setup necessary for wifi

) && connected=true

# later json will be returned based on if connected is set

답변1

메모:

  • wait $subshell$subshell실행 중인 프로세스의 자식이 아니기 때문에 작동하지 않습니다 wait. 어쨌든 프로세스가 수행될 때까지 기다리지 않으므로 wait별로 중요하지 않습니다.
  • kill $subshell서브쉘을 종료할 예정이지만 서브쉘이 실행될 sleep때까지 시작할 수 있었다면 그렇지 않습니다. 그러나 다음과 같은 프로세스에서 kill실행할 수 있습니다 .sleepexec
  • 메시지를 피하기 위해 SIGTERM 대신 SIGPIPE를 사용할 수 있습니다.
  • 목록 컨텍스트에서 변수를 따옴표로 묶지 않은 상태로 두는 것은 에서 매우 특별한 의미를 갖습니다 bash.

모든 것을 말한 후 다음을 수행할 수 있습니다.

(
  subshell=$BASHPID
  kill -s PIPE "$subshell" &
  sleep 600
)
echo subshell done

( 서브쉘뿐만 아니라 종료 하려는 경우 sleep 60로 바꾸십시오. 이 경우 종료할 때까지 실행될 시간조차 없을 수도 있습니다.)exec sleep 60killsleepsleep

어쨌든, 그걸로 무엇을 달성하고 싶은지 잘 모르겠습니다.

sleep 600 &

sleep원하는 경우(또는 기본 셸에서 (sleep 600 &)해당 프로세스를 숨기려는 경우 ) 백그라운드에서 시작하는 더 안정적인 방법이 될 것입니다.sleep

이제 실제

sudo stdbuf -o0 wpa_supplicant -Dwext -i"$wifi" -c/etc/wpa_supplicant/wpa_supplicant.conf

명령을 실행하기 위해 하위 프로세스를 생성한다는 점에 유의하십시오 sudo(상태를 기록하거나 나중에 일부 PAM 세션 작업을 수행해야 할 수 있기 때문에). stdbuf그러나 동일한 프로세스에서 실행되므로 결국에는 의 조상 wpa_supplicant에 세 개의 프로세스(나머지 스크립트 외에)가 있게 됩니다 .wpa_supplicant

  1. 서브쉘
  2. 1의 자식으로서의 sudo
  3. wpa_supplicant(이전에 stdbuf를 실행 중이었음)를 2의 하위로 사용

1개를 죽이면 자동으로 2개가 죽지 않습니다. 그러나 2개를 죽이면 가로챌 수 없는 SIGKILL과 같은 신호가 아닌 이상 sudo수신한 신호를 실행 명령에 전달하는 것처럼 3개가 죽습니다. .

어쨌든 여기서 죽이고 싶은 서브쉘은 아니고 3개 또는 적어도 2개입니다.

이제 스크립트가 다음과 같이 실행되고 root나머지 스크립트는 그렇지 않으면 그렇게 쉽게 종료할 수 없습니다.

kill다음 과 같이 수행 해야 하므로 다음 root이 필요합니다.

sudo WIFI="$wifi" bash -c '
  (echo "$BASHPID" &&
   exec stdbuf -o0 wpa_supplicant -Dwext -i"$WIFI" -c/etc/wpa_supplicant/wpa_supplicant.conf 2>&1
  ) | {
    read pid &&
      grep -m1 "pre-shared key may be incorrect" &&
      kill -s PIPE "$pid"
  }'

그렇게 하면 우리 wpa_supplicant가 .$BASHPIDexec

파이프를 통해 pid를 얻고 kill루트로 실행합니다.

조금 더 기다려 볼 준비가 되셨다면, 참고하세요.

sudo stdbuf -o0 wpa_supplicant -Dwext -i"$wifi" -c/etc/wpa_supplicant/wpa_supplicant.conf 2>&1 |
  grep -m1 "pre-shared key may be incorrect"

SIGPIPE를 사용하면 자동으로 종료 되었을 것입니다 wpa_supplicant(시스템에 의해 권한 문제가 없음).다음번grep사라진 후에 해당 파이프에 무언가를 씁니다 .

sudo일부 셸 구현은 after가 반환될 때 까지 기다리지 않으며 grep(SIGPIPEd를 얻을 때까지 백그라운드에서 실행 상태로 유지) 를 사용하면 after가 반환될 때까지 기다리지 않는 구문을 bash사용하여 이를 수행할 수도 있습니다 .grep ... <(sudo ...)bashsudogrep

자세한 내용은일치하는 항목을 찾은 후 Grep이 종료하는 데 속도가 느립니까?

답변2

bash -i서브쉘은 프롬프트 를 제공하는 대화형 로그인 쉘 의 하위와 같은 일부 쉘의 하위인 쉘 명령을 나타냅니다 $. 당신은하지 않습니다가지다서브셸에서 명령을 실행하려면 독립적인 프로세스로 실행하도록 선택할 수 있습니다. stdout / stderr이 진행률 표시줄의 모양을 엉망으로 만드는 것을 원하지 않고 부모 쉘이 자식의 죽음을 보고하거나 심지어 통지하는 것을 원하지 않기 때문에 이것이 적절할 수 있는 것처럼 들립니다.

이를 달성하기 위한 표준 도구가 있습니다.악마화하다그리고 안돼. (또한보십시오남성 페이지.) 당신은 다음과 같이 하는 것이 가장 좋을 것입니다.안돼. 다음은 이를 사용하여 간단한 프로그램을 실행하는 예입니다.~ 아니다nohup.out을 생성합니다:

$ nohup true 2>&1 > /dev/null &

프로그램이나 프로그램의 래퍼 스크립트에서 PID를 /tmp/my.pid에 기록하도록 하세요. bash에서는 이를 $$변수로 사용할 수 있습니다. 그런 다음 진행률 표시줄을 사용하여 모니터링 프로세스를 수행할 수 있습니다.

$ kill `cat /tmp/my.pid`

더 이상 처리를 수행하기 위해 해당 프로그램이 더 이상 필요하지 않은 경우. 또는 프로그램 이름을 에 지정하는 것이 좋습니다 killall.

답변3

당신은 이것을 찾고있을 것입니다

#!/bin/bash
(subshell=$BASHPID
  (kill $subshell & wait $subshell 2>/dev/null) &
sleep 600) &
wait $! 2>/dev/null

echo subshell done

여기서 하위 쉘은 백그라운드에 배치되고 상위 쉘은 기다리지만 대기 출력은 /dev/null로 전송됩니다. 이것은 Terminated메시지를 포착합니다.

예를 들어 출력을 파일로 캡처하기 위해 대기를 변경하면 다음과 wait $! 2>wait_output같이 표시됩니다.

 ./foo.sh: line 5:  1939 Terminated              ( subshell=$BASHPID; ( kill $subshell & wait $subshell 2> /dev/null ) & sleep 600 )

이것이 Terminated상위 쉘에서 나온 것임을 보여줍니다.

죽이기 전에 어떤 활동이 있었는지 확인하는 간단한 검사는 다음과 같습니다.

#!/bin/bash
(subshell=$BASHPID
 (sleep 1; kill $subshell & wait $subshell 2>/dev/null) &
sleep 600) & wait 2>wait_output

echo subshell done

이 예는 인쇄하기 전에 잠시 일시 중지됩니다 subshell done. 이 예는 또한 동일한 줄에서 모두 백그라운드로 대기하고 기다리는 방법을 보여줍니다 & wait 2>wait_output. .wait $!

여기서 주목해야 할 핵심 사항은 Terminated메시지가 최상위 상위 셸 작업 제어에서 온다는 것입니다. 이것이 서브쉘이 종료되는 것을 보고 메시지를 생성하는 것입니다. 이것이 바로 출력을 포착하려는 곳입니다. 명령 출력 을 리디렉션하면 wait이 작업이 수행됩니다.

관련 정보