Cela s'est avéré être causé par une condition de concurrence. cp
vérifie si le fichier de destination existe déjà et sinon - l'écrase. Le problème se produisait car cette cp
commande était exécutée deux fois en parallèle, ce qui faisait que le fichier en question apparaissait parfois après avoir vérifié s'il existait, mais avant la tentative de création du fichier. La strace
sortie ressemble à ceci:
# Command was "cp a b"
stat("b", 0x7fff89510620) = -1 ENOENT (No such file or directory)
stat("a", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
stat("b", 0x7fff895103a0) = -1 ENOENT (No such file or directory)
# File b will be created at this point in time
open("a", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
open("b", O_WRONLY|O_CREAT|O_EXCL, 0644) = -1 EEXIST (File exists)
Voici un code bash utilisé pour intercepter cela:
#!/bin/bash
touch a
f() {
while true; do
rm -f b
strace -o /tmp/cp${BASHPID}.trace cp a b || break
done
}
cleanup() {
kill -9 %1 %2
}
f &
f &
trap cleanup exit
wait
Cette même erreur peut se produire avec mkdir -p
ou toute autre action qui tente de remplacer un fichier. L'utilisation flock
peut aider à éviter les conditions de concurrence dans des cas comme celui-ci.
||
opérateur. Sorte de tentative / prise d'un poorman. -À- dire,cp ... || echo "skip copying due to other thread"
. Ou quelque chose de similaire ...cp
cp
.