GNU/Linux >> Znalost Linux >  >> Linux

Přesunout soubor, ale pouze pokud je zavřený

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).


Linux
  1. Jak zjistit, který proces vytváří soubor?

  2. Linux – Spustit pouze oprávnění k souboru?

  3. Facl Ignoruje oprávnění „x“, ale pouze u souborů?

  1. Jak posunout řádek v textovém souboru nahoru nebo dolů o jeden řádek?

  2. Jak přesměrovat pouze Stderr?

  3. Zrušit dokončení, ale pouze dokončení, v Zsh?

  1. Přesunout soubory v terminálu Linux

  2. Základní příkazy vi (cheat sheet)

  3. přesunout pouze v případě, že soubor existuje ve skriptu shellu