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?
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
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.
octane@alinto.com :
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.
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.