Esto resultó ser causado por una condición de carrera. cp
comprueba si el archivo de destino ya existe y, si no, lo sobrescribe. El problema estaba sucediendo porque este cp
comando se ejecutaba dos veces en paralelo, lo que ocasionaba que el archivo en cuestión apareciera a veces después de verificar si existía, pero antes del intento de crear el archivo. El strace
resultado se ve así:
# 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)
Aquí hay un código bash utilizado para atrapar esto:
#!/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
Este mismo error puede ocurrir con mkdir -p
cualquier otra acción que intente sobrescribir un archivo. Usar flock
puede ayudar a evitar condiciones de carrera en casos como este.
||
operador. Una especie de intento / captura de un pobre. Es decir,cp ... || echo "skip copying due to other thread"
. O algo similar ...cp
cp
.