OVH Cloud OVH Cloud

acces concurrentiel sur un fichier

1 réponse
Avatar
octane
Bonjour,

j'ai un probleme avec un script.

Soit un fichier logfile.conf:
$ cat logfile.conf
# @(#)B.11.11_LR
#
# syslogd configuration file.
#
# See syslogd(1M) for information about the format of this file.
#
mail.debug /var/adm/syslog/mail.log
*=2Einfo;mail.none /var/adm/syslog/syslog.log
*=2Ealert /dev/console
*=2Ealert root
*=2Eemerg *
# logfile ID=3Dsyslog
*=2Eemerg;*.alert;*.crit;*.err;*.warning;*.notice;*.info /tmp/tmp.fifo
# logfile ID=3Dsyslog

J'ai dans un script une commande awk qui me nettoie les 3 dernieres
lignes:
$ cat update_conf
#! /bin/sh
PID=3D$$
awk '/# logfile ID=3D'$4'/,/# logfile entry, ID=3D'$4'/ {next;} \
{print $0}' $3 > $3.$PID
cp $3.$PID $3
rm $3.$PID

Ce script fonctionne tres bien tant que je le lance une fois par une
fois. Si les lignes logfile sont pr=E9sentes, il les supprime, si elles
ne
sont pas la, il ne fait rien.

Si je lance une boucle comportant:
while (...) do
update_conf $1 $2 logfile.conf syslog &
done

immanquablement (et au bout de tres peu de boucles) le
fichier logfile.conf se retrouve integralement vide.

Je ne comprends pas pourquoi. Je pense qu'un acces concurrent est
effectue sur ce fichier mais je ne comprends pas pourquoi il se vide?

Une idee?

Merci

1 réponse

Avatar
lhabert
:

cp $3.$PID $3
rm $3.$PID


Cp fonctionne en écrasant le contenu du fichier de destination, puis en
recopiant à la place le contenu de la source. Bref, c'est presque comme si
tu faisais un « cat "$3.$PID" > "$3" ». Donc tu as un intervalle de temps
pendant lequel le fichier est vide. Si tu en lances plusieurs en même temps,
il y a fatalement un awk qui va lire le fichier à un moment où il est vide,
et donc générer une sortie vide, et donc écrabouiller le fichier de départ
(à ce stade là, c'est pas forcément fichu parce que tu en as peut-être un
autre lancé en même temps qui a lu le fichier alors qu'il était plein et va
donc le restaurer, mais ça va bien finir par casser un jour...).

Une solution meilleure consiterait à faire un « mv "$3.$PID" "$3" » qui a
pour effet de modifier le fichier pointé par le nom de fichier $3, sans
toucher au contenu d'aucun fichier, si bien qu'à tout moment, l'ouverture du
fichier $3 renvoie un fd sur un fichier complet.

Il se peut que ça ne soit pas encore ce que tu veux, imagine le scénario
suivant :

- tu lances ton script sur le fichier « ploum », il lance un awk qui
commence à créer un « ploum.xxx ». Pour une raison quelconque l'OS décide
que ce awk est pas gentil et arrête de lui donner la main
- un autre programme modifie « ploum »
- tu lances une deuxième fois ton script, et il se termine assez vite
- l'OS finit par redonner la main à la première version de ton script.

Tu vas te retrouver avec une version nettoyée de la première version de
ploum, au lieu de la deuxième version, qui était probablement celle que tu
aurais voulue.