Це виявилося причиною перегонів. cp
перевіряє, чи існує цільовий файл, а якщо ні - перезаписує його. Проблема сталася через те, що ця cp
команда виконувалась двічі паралельно, що спричинило виникнення відповідного файлу іноді після перевірки того, чи існує він, але перед спробою створення файлу. strace
Результат виглядає наступним чином :
# 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)
Ось кілька баш-кодів, які використовуються для цього:
#!/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
Ця ж помилка може статися при mkdir -p
будь-якій іншій дії, яка намагається перезаписати файл. Використання flock
може допомогти уникнути перегонів у таких випадках.
||
оператора. Сорт спроби / улову бідняка. Тобто,cp ... || echo "skip copying due to other thread"
. Або щось подібне ...