Я записал сценарий оболочки ниже для лаборатории в моем колледже. Это должно посмотреть на файл журнала, обновляемый часто от другого процесса, и создать много копий, переданных при вызове. Вот код (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 (logtest.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);
}
- и сценарий оболочки (logtest.sh):
#! /bin/bash
while true
do
echo $(date) >> log
sleep 1
done
Когда я запускаюсь
./logtest.sh и
Журнал./logrotate.sh
сценарий logrotate.sh перемещает все файлы с корректными именами (журнал становится журналом 1), и отправьте сигнал в процесс, который владеет журналом файла в течение того момента (так сценарий оболочки logtest.sh), который затем продолжает писать на журнале файла. Кроме того, кажется, что нет никакого различия, о котором сигнале я отправляю с термофиксатором: это будет всегда реагировать тот же путь.
Однако, если я запускаюсь
./logtest и
Журнал./logrotate.sh
это происходит, что программа C logtest получает сигнал от термофиксатора команды и затем завершается.
Мой вопрос: почему две программы входа имеют различные реакции на сигнал, отправленный от термофиксатора? Я имею в виду, почему сценарий оболочки продолжает работать, пока программа C завершается?
В странице справочника термофиксатора в разделе RESTRICTIONS это говорит
-k опция только работает над процессами.
Могло случиться так, что сценарии оболочки не рассматривают как реальные процессы в оболочке? Это было бы новым для меня... Я искал в Интернете, но никакая страница, найденная о термофиксаторе, не идет глубоко в сигнальном разделе.
Проблема состоит в том, что 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
конец цикла.
Ваш сценарий logtest.sh
действительно только вписывает log
и сразу закрывает дескриптор файла. Таким образом, когда Вы звоните fuser
на log.1
нет никакого процесса, который имеет активный дескриптор файла для этого файла.
Можно моделировать это путем выполнения while
цикл внутри a list
(while true; do echo $(date); sleep 1; done) >> log
И оба logtest.sh
и logtest.c
завершится, неважно, который SIGNAL
Вы отправляете, потому что Вы не обрабатываете сигнал. С bash
это может быть, покончили trap '<COMMAND>' USR1
(смотрите на man bash-builtins
). Но я понятия не имею, как это сделано в C (никогда lerned C).