Z lsof
manuálová stránka
Lsof vrátí jedničku (1), pokud byla zjištěna nějaká chyba, včetně toho, že se nepodařilo najít názvy příkazů, názvy souborů, internetové adresy nebo soubory, přihlašovací jména, soubory NFS, PID, PGID nebo UID, o jejichž uvedení byl požádán. Pokud je zadáno -Voption, lsof bude označovat položky hledání, které se nepodařilo vypsat.
To by znamenalo, že vaše lsof failed for some other reason
klauzule by nikdy nebyla provedena.
Zkusili jste jen přesunout soubor, zatímco váš externí proces ho má stále otevřený? Pokud je cílový adresář na stejném souborovém systému, pak by s tím neměly být žádné problémy, pokud k němu nepotřebujete přistupovat pod původní cestou z třetího procesu, protože základní inode zůstane stejný. Jinak myslím mv
stejně selže.
Pokud opravdu potřebujete počkat, až váš externí proces dokončí soubor se souborem, je lepší použít příkaz, který blokuje místo opakovaného dotazování. V systému Linux můžete použít inotifywait
pro tohle. Např.:
inotifywait -e close_write /path/to/file
Pokud musíte použít lsof
(možná kvůli přenositelnosti), můžete zkusit něco jako:
until err_str=$(lsof /path/to/file 2>&1 >/dev/null); do
if [ -n "$err_str" ]; then
# lsof printed an error string, file may or may not be open
echo "lsof: $err_str" >&2
# tricky to decide what to do here, you may want to retry a number of times,
# but for this example just break
break
fi
# lsof returned 1 but didn't print an error string, assume the file is open
sleep 1
done
if [ -z "$err_str" ]; then
# file has been closed, move it
mv /path/to/file /destination/path
fi
Aktualizovat
Jak poznamenal níže @JohnWHSmith, nejbezpečnější návrh by vždy používal lsof
smyčka, jak je uvedeno výše, protože je možné, že více než jeden proces bude mít soubor otevřený pro zápis (příkladem může být špatně napsaný indexovací démon, který otevírá soubory s příznakem čtení/zápisu, když by měl být skutečně pouze pro čtení). inotifywait
lze však stále používat místo spánku, stačí nahradit řádek spánku kódem inotifywait -e close /path/to/file
.
Jako alternativní přístup je to perfektní případ pro potrubí - druhý proces zpracuje výstup z prvního procesu, jakmile bude k dispozici, místo aby čekal na dokončení celého procesu:
process1 input_file.dat | process2 > output_file.dat
Výhody:
- Obecně mnohem rychlejší:
- Nemusí zapisovat a číst z disku (tomu se lze vyhnout, pokud používáte ramdisk).
- Měl by úplněji využívat zdroje stroje.
- Žádný přechodný soubor k odstranění po dokončení.
- Není nutné žádné složité zamykání jako v OP.
Pokud nemáte žádný způsob, jak přímo vytvořit rouru, ale máte GNU coreutils můžete použít toto:
tail -F -n +0 input_file.dat | process2 > output_file.dat
Tím se zahájí čtení vstupního souboru od začátku, bez ohledu na to, jak daleko první proces spočívá v zapsání souboru (i když ještě nebyl spuštěn nebo již skončil).