퓨저로부터 신호를 받는 C 프로그램과 쉘 스크립트의 차이점

퓨저로부터 신호를 받는 C 프로그램과 쉘 스크립트의 차이점

저는 대학 연구실을 위해 아래 쉘 스크립트를 작성했습니다. 다른 프로세스에서 자주 업그레이드되는 로그 파일을 확인하고 호출 시 전달되는 여러 복사본을 생성해야 합니다. 다음은 코드입니다(logrotate.sh):

#!/bin/bash

# Usage:
#   logrotate.sh [-n int] [-s signal] logfile
# where:
#   int is an optional integer used to make int number of copies of logfile
#   signal is the name of signal which shell command fuser must send to the process managing logfile
# this script lacks of a strong parameters checking

NCOPIES=4  
LOGSIGNAL=USR1

#use of getopts to parse the arguments  
while getopts "n:s:" OPTION ; do  
    case $OPTION in  
        n) NCOPIES="$OPTARG"  
           ;;  
        s) LOGSIGNAL="$OPTARG"  
           ;;  
        ?) printf "Usage: %s [-n copies to keep] [-s signal to send] filename\n" $(basename $0) >&2  
        exit 1  
           ;;  
    esac  
done  
#shift to read the last parameter (logfile)  
shift $(($OPTIND - 1))  
LOGFILE=$1  

#create logfile.2 logfile.3 ... logfile.NCOPIES  
for i in `seq $NCOPIES -1 1` ; do  
    test -f $LOGFILE.$i && mv $LOGFILE.$i $LOGFILE.$[ $i + 1 ]  
done  

mv $LOGFILE $LOGFILE.1  

#sending signal to process which is writing to logfile to keep on writing to $LOGFILE(original name, without any extensions)  
fuser -k -"$LOGSIGNAL" $LOGFILE.1  

그래서 매초마다 파일에 쓰는 두 개의 스크립트를 작성했습니다.통나무:
-C 프로그램(로그테스트.c):

#include <stdio.h>  
#include <stdlib.h>   
#include <fcntl.h>  
#include <unistd.h>  

int main()  
{  
    int fd = open("log", O_WRONLY | O_APPEND);  
    if(fd < 0 ){  
        printf("Impossible to open file %s.\n", "log");  
        return -1;  
    }  
    for(;;){  
        if(write(fd, "Ciao bello mio\n", 15) != 15){  
            write(2, "Error in writing data.\n", 23);  
        }  
        sleep(1);  
    }  
    close(fd);  
    exit(0);  
}  

-그리고 쉘 스크립트(로그테스트.sh):

#! /bin/bash  

while true 
do
    echo $(date) >> log
    sleep 1
done  

내가 시작할 때

./logtest.sh &
./logrotate.sh 로그

대본logrotate.sh올바른 이름의 모든 파일을 이동합니다(통나무된다로그.1) 파일을 소유한 프로세스에 신호를 보냅니다.통나무그 순간(그래서 쉘 스크립트는로그테스트.sh) 그런 다음 파일에 계속 씁니다.통나무. 게다가 퓨저로 보내는 신호에는 차이가 없는 것 같습니다. 퓨저가 항상 같은 방식으로 반응할 것입니다.

그러나 내가 실행하면

./logtest &
./logrotate.sh 로그

C 프로그램이로그 테스트명령으로부터 신호를 받습니다퓨저그런 다음 종료됩니다.

내 질문은: 왜 두 로깅 프로그램이 퓨저에서 전송된 신호에 대해 서로 다른 반응을 보이는가입니다. C 프로그램이 종료되는 동안 schell 스크립트는 계속 작동하는 이유는 무엇입니까?

RESTRICTIONS 섹션의 퓨저 매뉴얼 페이지에는 다음과 같이 나와 있습니다.

-k 옵션은 프로세스에서만 작동합니다.

쉘 스크립트가 쉘에서 실제 프로세스로 간주되지 않을 수 있습니까? 이것은 나에게 새로운 것입니다... 인터넷에서 검색했지만 관련 페이지를 찾을 수 없습니다.퓨저신호 섹션 안으로 깊숙이 들어가 보세요.

답변1

귀하의 스크립트는 파일 설명자 logtest.sh에 즉시 쓰고 닫습니다. log따라서 호출할 때 fuserlog.1파일에 대한 활성 파일 설명자를 갖는 프로세스가 없습니다.

while내부에서 루프를 실행하여 이를 시뮬레이션할 수 있습니다 .list

(while true; do echo $(date); sleep 1; done) >> log

그리고 신호를 처리하지 않기 때문에 무엇을 보내든 logtest.sh및 둘 다 종료됩니다. 이 작업은 다음을 통해 수행할 수 있습니다 ( 참조 ). 그러나 나는 이것이 C에서 어떻게 수행되는지 전혀 모릅니다(C를 배운 적이 없습니다).logtest.cSIGNALbashtrap '<COMMAND>' USR1man bash-builtins

답변2

문제는 fuser현재 커널에 파일 설명자가 열려 있는 파일을 사용하는 프로세스에서만 작동한다는 것입니다.

이는 프로그램에는 해당되지만 C스크립트에는 해당되지 않습니다 bash.

echo $(date) >> log

파일을 열고 추가한 stdout다음 즉시 닫습니다. 따라서 파일은 fuser의 확인 시 커널에 의해 열린 것으로 간주되지 않습니다 .

간단한 해결책은 루프가 끝날 bash때까지 파일이 열려 있도록 스크립트를 변경하는 것입니다 while.

#! /bin/bash  

while true 
do
    echo $(date) >> log
    sleep 1
done < log

이런 방식으로 루프 시작 시 파일 설명자가 log생성되고 루프가 끝날 while때까지 열린 상태로 유지됩니다 .while

관련 정보