C程式和shell腳本從fuser接收訊號的區別

C程式和shell腳本從fuser接收訊號的區別

我為我大學的一個實驗室編寫了下面的 shell 腳本。它必須查看從另一個進程頻繁升級的日誌文件,並創建在呼叫時傳遞的多個副本。這是代碼(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);  
}  

- 和 shell 腳本 (日誌測試.sh):

#! /bin/bash  

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

當我啟動時

./logtest.sh &
./logrotate.sh 日誌

劇本logrotate.sh移動所有具有正確名稱的檔案(紀錄變成日誌.1)並將訊號傳送到擁有該檔案的進程紀錄那一刻(所以 shell 腳本日誌測試.sh)然後繼續寫入文件紀錄。此外,我用定影器發送的信號似乎沒有區別:它總是以相同的方式做出反應。

但是,如果我啟動

./logtest &
./logrotate.sh 日誌

碰巧 C 程序對數測試接收來自命令的訊號定影器然後終止。

我的問題是:為什麼兩個日誌程式對從定影器發送的訊號有不同的反應?我的意思是,為什麼 schel 腳本繼續工作,而 C 程式終止?

在定影器的手冊頁的限制部分中,它說

-k 選項僅適用於進程。

難道shell腳本不被認為是shell中的真實進程嗎?這對我來說是新的......我在互聯網上搜索過,但沒有找到有關的頁面定影器深入了解訊號部分。

答案1

您的腳本logtest.sh只會立即寫入log並關閉檔案描述符。因此,當您呼叫時,fuser沒有log.1進程具有該檔案的活動檔案描述符。

while您可以透過在 a 中運行循環來模擬這一點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

這樣,文件描述符 forlog在循環開始時創建while,並保持打開狀態直到while循環結束。

相關內容