Re: [Lug-bg] Bash gimnastiki
- Subject: Re: [Lug-bg] Bash gimnastiki
- From: George Danchev <danchev@xxxxxxxxx>
- Date: Sat, 24 Oct 2009 20:41:40 +0200
> Здравейте,
Драсти,
> Искам първо да вметна, че не съм програмист и ползвам BASH от дъжд на
> вятър, т.е. пълен лаик.
>
> Ето и какво ме накара да пиша тук:
> Реших с помощта на rrdtool да чертая графика на прихванатите вируси от
> антивирусната ми програма. За целта си направих един "прост" BASH скрипт,
> който се изпълнява с помощта на procmail, когато се прихване вирус от
> антивирусната програма, като целта му е да увеличава с единица стойността
> на едно число - индекс:
>
>
> #!/bin/bash
>
> virusvar=`/bin/cat /etc/rrdtool/mail/virus-count`
> ((virusvar++))
> /bin/echo -n $virusvar > /etc/rrdtool/virus/virus-count
>
>
>
> Всичко си сработва много добре, но когато сървъра се натовари (т.к. си е
> бая стар и е с много малко RAM памет) поредността на числото, което се
> записва във virus-count се обърква. Прави ми впечатление, че това се
> случва в момент, когато е натоварен и четенето/писането от и във
> virus-count става в почти един и същи момент.
>
> Много съм любопитен да разбера защо се случва това?
Накратко, както обяси и Пенчев, твоя скрипт не е reentrant, т.е. не е
здравословно за се влиза в него докато предното му изпълнение не е приключило
защото има споделен ресурс, т.е. файла и цялата операция става неопределена.
Ето ти още две решения:
1) брутално: procmail вика mktemp който създава празни файлове с уникални
имена в дадена директория и ти ги бройкаш от време на време - нямам споделен
ресурс, няма да хаби дисково пространство, и едва ли ше удариш лимита по брой
файлове на файловата система ;-)
2) чрез signal handlers (фнимателно със signal handlers, да са много леки)
http://www.gnu.org/software/libc/manual/html_node/Nonreentrancy.html#Nonreentrancy
компилираш следната програмка:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
/* This variable is set by the SIGALRM signal handler. */
volatile sig_atomic_t flag = 0;
/* Ugly global counter */
volatile long c = 0;
void print_event() {
fprintf(stdout, "%ld\n", c);
};
void register_event() {
++c;
};
int main (void)
{
signal(SIGALRM, register_event);
signal(SIGUSR1, print_event);
sigset_t block_alarm;
/* Initialize the signal mask. */
sigemptyset (&block_alarm);
sigaddset (&block_alarm, SIGALRM);
while (1) {
/* Check if a signal has arrived; if so, reset the flag. */
sigprocmask (SIG_BLOCK, &block_alarm, NULL);
if (flag)
flag = 0;
sigprocmask (SIG_UNBLOCK, &block_alarm, NULL);
}
}
Казваш на procmail да й праща SIGALRM с kill -s когато дойде вирус (това е
доста по-бързо от отваряне и писане във файл;-), а ти можеш да я тестваш за
дуракоустойчивост така, ако приемем, че се казва a.out:
пращаш бройка сигнали (все едно пратени от procmail):
for a in `seq 1 100`; do kill -s SIGALRM `pidof a.out`; done
питаш я колко са получени:
kill -s SIGUSR1 `pidof a.out`
(трябва да е стартирана разбира се и пише на stdout)
--
pub 4096R/0E4BD0AB <people.fccf.net/danchev/key pgp.mit.edu>
Attachment:
signature.asc
Description: This is a digitally signed message part.
_______________________________________________
Lug-bg mailing list
Lug-bg@xxxxxxxxxxxxxxxxxx
http://linux-bulgaria.org/mailman/listinfo/lug-bg
|