Okazało się, że jest to spowodowane warunkami wyścigowymi. cpsprawdza, czy plik docelowy już istnieje, a jeśli nie - zastępuje go. Problem występował, ponieważ to cppolecenie było uruchamiane dwukrotnie równolegle, co powodowało, że dany plik czasami pojawiał się po sprawdzeniu, czy istnieje, ale przed próbą utworzenia pliku. Dane stracewyjściowe wyglądają następująco:
# 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)
Oto kod bash używany do tego:
#!/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
Ten sam błąd może wystąpić podczas mkdir -pdowolnej akcji, która próbuje zastąpić plik. Używanie flockmoże pomóc w uniknięciu warunków wyścigowych w takich przypadkach.
||operatora. Coś w rodzaju próbowania / połowu przez robaka. Tjcp ... || echo "skip copying due to other thread". Lub coś podobnego ...