nie można utworzyć zwykłego pliku „nazwa pliku”: plik istnieje

23

Otrzymałem ten dziwny komunikat o błędzie w jednym ze skryptów kompilacji - błąd cpkończy się, zwracając błąd „Plik istnieje”. Próbowałem nawet użyć cp -f, który powinien zastąpić plik, jeśli istnieje, ale błąd nadal się pojawia. Uruchamianie w cpcelu zastąpienia istniejących plików działa idealnie, gdy robię to ręcznie. Co może powodować ten błąd?

lutzky
źródło

Odpowiedzi:

25

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.

lutzky
źródło
Natrafiłem na tę samą sytuację. Zdecydowałem się obsłużyć to za pośrednictwem ||operatora. Coś w rodzaju próbowania / połowu przez robaka. Tj cp ... || echo "skip copying due to other thread". Lub coś podobnego ...
icfantv
cp
Uderzyłem
Wpadłem na ten sam problem. Jak to debugowałeś?
CIsForCookies
Znalazłem sposób na porażkę cp.
lutzky