C 程序和 shell 脚本从 fuser 接收信号之间的区别

C 程序和 shell 脚本从 fuser 接收信号之间的区别

我为我大学的一个实验室编写了下面的 shell 脚本。它必须查看从另一个进程频繁升级的日志文件,并在调用时创建多个副本。以下是代码(日志旋转命令):

#!/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);  
}  

- 和 shell 脚本(日志测试工具):

#! /bin/bash  

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

当我启动时

./logtest.sh &
./logrotate.sh 日志

剧本日志旋转命令移动所有具有正确名称的文件(日志变成日志1)并将信号发送给拥有该文件的进程日志那一刻(所以 shell 脚本日志测试工具)然后继续在文件上写入日志。此外,似乎我用定影器发送的信号没有区别:它总是以相同的方式做出反应。

但是,如果我启动

./logtest &
./logrotate.sh 日志

碰巧的是 C 程序日志测试接收来自命令的信号定影器然后终止。

我的问题是:为什么这两个日志程序对 fuser 发送的信号有不同的反应?我的意思是,为什么 schell 脚本继续工作,而 C 程序终止了?

在 fuser 的手册页中的 RESTRICTIONS 部分中,它说

-k 选项仅适用于进程。

难道 shell 脚本不被视为 shell 中的真正进程?这对我来说是新鲜事……我在互联网上搜索过,但没有找到关于定影器深入信号部分。

答案1

您的脚本logtest.sh仅写入log并立即关闭文件描述符。因此,当您调用时,fuser没有log.1进程具有此文件的活动文件描述符。

您可以通过whilelist

(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循环结束。

相关内容