bash: CTRL-C와 "순서적 정리" 간의 출력이 다릅니다.

bash: CTRL-C와 "순서적 정리" 간의 출력이 다릅니다.

저는 이 질문에 대한 더 나은 제목을 찾으려고 노력하고 있습니다. 나는 제안에 열려 있습니다.

EXIT신호가 수신되면 함수를 포착하고 호출하는 bash 스크립트를 작성했습니다 . 호출된 파일이 존재할 때 stop동일한 함수를 호출합니다 . 여기있어:

#!/bin/bash

TAIL_PID=0
CAT_PID=0

DEVICE=/dev/ttyACM0
WDIR=plasma
LOGFILE=$WDIR/$(date +%Y%m%d_%H%M%S.log)
CMDFILE=$WDIR/toDevice

function kill_tail
{
  if [ $TAIL_PID -ne 0 ]
  then
    kill $TAIL_PID
    TAIL_PID=0
    echo "killed tail"
  fi
}

function kill_cat
{
  if [ $CAT_PID -ne 0 ]
  then
    kill $CAT_PID
    CAT_PID=0
    echo "killed cat"
  fi
}

function on_die
{
  echo 't 0' >> $DEVICE
  kill_tail
  kill_cat
  echo "stopped logging"
}
trap on_die EXIT

# mount plasma oven directory if it is not already mounted
mountpoint -q $WDIR || sshfs user@server:plasma $WDIR    
# see if device is available/wait for device
while [ ! -c $DEVICE ]
do
  sleep 1
done
echo "Found controller"

# stop output, remove start and stop files
echo 't 0' >> $DEVICE
rm $WDIR/start $WDIR/stop

# outer loop
while [ 1 ]
do
  while [ ! -f $WDIR/start ]
  do
    sleep 1
  done
  rm $WDIR/start

  # stop output
  echo 't 0' >> $DEVICE

  # pass commands to device
  # but clear existing commands first
  > $CMDFILE
  tail -f $CMDFILE > $DEVICE &
  TAIL_PID=$!
  echo "tail PID = " $TAIL_PID

  # start logging
  cat $DEVICE >> $LOGFILE &
  CAT_PID=$!
  echo "cat PID = " $CAT_PID

  # start output
  echo 't 1000' >> $DEVICE
  echo "started logging to " $LOGFILE

  while [ ! -f $WDIR/stop ]
  do
    sleep 1
  done
  rm $WDIR/stop

  on_die

done # end of outer loop

이 스크립트를 실행하면 I 또는 ing을 touch start기반으로 출력이 생성됩니다 .CTRL-Ctouch stopCTRL-C

killed tail
killed cat
stopped logging

이후의 출력은 다음과 같습니다 touch stop.

killed tail
killed cat
stopped logging
./mountPlasma: line 93: 21200 Terminated              tail -f $CMDFILE > $DEVICE
./mountPlasma: line 93: 21201 Terminated              cat $DEVICE >> $LOGFILE

왜? 동일한 함수를 호출하면 두 호출 모두에 대해 동일한 출력이 필요합니다 on_die. 출력에서는 93행에서 두 개의 추가 메시지가 발행되었음을 보여줍니다 done # end of outer loop(이 기사에서는 몇 줄을 제거해야 했기 때문에 행 번호가 위 코드와 정확히 일치하지 않습니다).

나는 bash에 대한 경험이 없기 때문에 이것이 부작용이 있는지 모르겠습니다. 그는 예상대로 살해당했습니다 tail.cat

답변1

을 클릭하면 Ctrl-C실행 중인 스크립트가 SIGINT를 가져와 하위 항목에 전파하고 "일반" 종료 시 기본 SIGTERM( 를 사용하여 등록된 함수에서 EXIT)을 보냅니다.

Ctrl-C즉, 정지조건의 차이가 크다. 두 경우 모두 종료 핸들러 함수가 호출되지만 실제 이벤트는 완전히 다릅니다. SIGINT의 경우 하위 프로세스는 해당 프로세스에 의해 종료됩니다(또는 적어도 종료될 수 있음).그리고스크립트를 해석하는 쉘은 이 상태 변경을 보고할 기회가 많지 않습니다. 다른 경우에는 캡처됩니다.신호등종료된 프로그램에서 정보 메시지를 표시합니다.

이제 해석 쉘에 확인할 충분한 시간을 제공하면 SIGINT에서 메시지를 얻을 수도 있습니다(보다 정확하게는 쉘이 떠날 것이라고 생각하지 않기 때문입니다)좀비 프로세스이 경우에는--보고 상태) 해당 하위 프로세스. 한 가지 접근 방식은 wait내장 함수를 사용하여 모든 프로세스 또는 지정된 프로세스가 상태를 변경할 때까지 적극적으로 기다리는 것입니다. 종료 핸들러를 폭파하는 것(예: 다른 핸들러 사용 sleep)도 옵션일 수 있지만 이는 실제로 인터프리터 종료와 하위 확인 사이의 경쟁 조건이라는 점에 유의하십시오(따라서 차단은 wait이를 수행하는 안전한 방법입니다).

관련 정보