S'il y avait un processus continuellement écrit dans un fichier et que je voulais prendre le contrôle du fichier avec root, je pouvais faire quelque chose comme ceci:
sudo rm somefile; sudo touch somefile
Est-il possible que le processus d'ajout soit ajouté au fichier entre ces deux commandes? Si oui, existe-t-il un moyen de garantir qu'aucune autre commande ne soit exécutée entre les deux?
Réponses:
Une ligne de commande chaînée est essentiellement un petit script shell; il exécutera la première commande en utilisant la procédure fork + exec habituelle, attendez qu'elle se termine, puis exécutez la seconde de la même manière. Entre les deux commandes, il y a un certain temps arbitraire que le shell prend dans sa comptabilité et son traitement, pendant lequel le multitraitement ordinaire a lieu et d'autres processus arbitraires peuvent faire d'autres choses arbitraires. Donc la réponse est non'. (Si vous faites cela, vous constaterez que l'entrée de répertoire de
somefile
disparaît, mais le fichier lui-même reste (puisqu'il est ouvert par un processus) jusqu'à sa fermeture. L'espace disque utilisé par le fichier ne sera pas récupéré jusqu'à ce que cela se produise. , latouch
commande créera un nouveau fichier sans rapport avec le même nom et le même chemin d'accès.)Si vous voulez changer la propriété du fichier en root, faites-le
sudo chown root:root somefile
(bien que je ne sais pas comment cela affectera les processus avec un descripteur de fichier ouvert). Si vous souhaitez détruire le contenu du fichier actuel, essayeztruncate -s 0 somefile
(le processus en cours continuera de s'ajouter au fichier maintenant vide). Si c'est autre chose, clarifiez peut-être ce que vous voulez faire.la source
chown
ing somefile n'affectera pas les processus qui ont un handle de fichier vers somefile.exec 3>somefile; sudo chmod 0600 somefile; echo hello world >&3; sudo cat somefile; exec 3>&-
.Non. Une
rm
commande suivie d'unetouch
commande n'est pas atomique du tout. Il s'écoulera beaucoup de temps entre les deux commandes, éventuellement dans la plage des millisecondes. Beaucoup de choses peuvent se produire pendant cette période. Si vous n'avez pas de chance, vos informations d'identification sudo peuvent même expirer.Un seul programme appelant les appels
unlink
etopen
laisserait une fenêtre beaucoup plus courte pour une course, mais cela pourrait encore arriver.Une approche plus sûre serait de créer le nouveau fichier avec un nom temporaire et d'utiliser l'
rename
appel système. "Remplacer" un nom avec l'rename
appel système est garanti atomique. Ceci pourrait être réalisé en utilisanttouch
etmv
.Mais un processus qui a ouvert l'ancien fichier pour l'écriture peut continuer à y écrire longtemps après sa suppression. Ce sera le cas à la fois pour un fichier supprimé à l'aide
unlink
et pour un fichier supprimé à l'aiderename
.la source
Une fois qu'un processus a un descripteur de fichier ouvert pour la lecture, peu importe ce que vous faites avec la propriété ou les autorisations: le processus peut continuer à accéder au fichier. Vous pouvez même supprimer le fichier et le processus pourra continuer à y accéder via le descripteur de fichier.
Considérez les autorisations comme une porte de contrôle pour obtenir un descripteur de fichier.
Si vous souhaitez créer un fichier de manière atomique, au lieu de faire ceci:
vous pourriez considérer ceci:
qui remplacera atomiquement
somefile
paranotherfile
. (J'aurais préféré utilisermv -f
mais je ne trouve pas de déclaration garantissant que cela appelle l'rename(2)
appel système.Vous pourriez peut-être mettre à jour votre question pour expliquer ce que vous entendez par «prendre le contrôle du fichier». Vous pouvez avoir un problème XY ici.
la source
mv -f
pour obtenir unrename(2)
appel système. Vous avez raisonln
, car il utilise toujours l'link(2)
appel système, qui ne peut pas remplacer atomiquement.ln -f
fait justeunlink(2)
sur la cible en premier.ln
sur le cerveau. Je ne savais pas trop commentrename(2)
m'impliquer et il était trop tard pour aller plus loinmv
"doit effectuer des actions équivalentes à"rename(old, new)
. pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html .mv -f
agit commemv -i
si la destination n'est pas accessible en écriture, mais ce n'est pas le cascp -f
ouln -f
là où elle se dissociera en premier.Non mais
sudo rm somefile; sudo touch somefile
est sûr dans la plupart des situations.
La plupart des processus ouvrent des fichiers, puis utilisent le descripteur de fichier acquis pour accéder au contenu du fichier.
Si un processus ouvre un fichier, en sh:
Ensuite, un autre processus est libre de dissocier (= supprimer) certains fichiers et le descripteur de fichier sur lequel certains fichiers était ouvert par le premier processus (3 dans ce cas) continuera de faire référence au contenu d'origine de certains fichiers, qui est maintenant un fichier dans les limbes.
créera un nouveau fichier non lié et tous les processus qui avaient l'ancien fichier ouvert et qui n'utilisent désormais qu'un descripteur de fichier pour s'y référer ne seront pas affectés car ils se réfèrent à un fichier différent - celui qui est maintenant dans les limbes.
Si un processus non root tente de faire référence à un fichier par son nom, il obtiendra une erreur EPERM, car le nouveau somefile appartient à la racine.
Si vous souhaitez empêcher plusieurs processus sous le même utilisateur (par exemple, root) de corrompre un fichier, Linux a un verrouillage de fichier obligatoire et consultatif. Vous pouvez utiliser la
flock
commande dans les scripts shell pour le verrouillage des fichiers (consultez la page de manuel pour plus d'informations).la source