GNU/Linux >> Znalost Linux >  >> Linux

Zkontrolujte, zda deskriptor souboru odkazuje na smazaný soubor (v Bash)

Chcete-li otestovat, zda deskriptor souboru odkazuje na běžný soubor, který nemá žádný zbývající odkaz v žádném adresáři v souborovém systému, můžete vytvořit fstat() systémové volání a zkontrolujte počet odkazů (st_nlink pole) ve vrácené struktuře.

S zsh , můžete to udělat s jeho stat vestavěný:

zmodload zsh/stat
fd=3
if
  stat -s -H st -f $fd &&   # can be fstat'ed (is an opened fd)
    [[ $st[mode] = -* ]] && # is a regular file
    ((st[nlink] == 0))      # has no link on the filesystem
then
  print fd $fd is open on a regular file that has no link in the filessystem
fi

bash (GNU shell) nemá ekvivalent, ale pokud používáte GNU systém, můžete mít GNU stat v takovém případě byste měli být schopni udělat něco jako:

fd=3
if [ "$(LC_ALL=C stat -c %F:%h - <&"$fd")" = 'regular file:0' ]; then
  printf '%s\n' "fd $fd is open on a regular file that has no link in the filessystem"
fi

Pokud je vaše jádro operačního systému Linux, přenosnější přístup (pro operační systémy, které nemají zsh a kde základní nástroje nepocházejí z GNU), za předpokladu, že souborový systém proc je připojen na /proc může být použití ls na /proc/self/fd/$fd :

if
  LC_ALL=C TZ=UTC0 ls -nLd /proc/self/fd/0 <&"$fd" |
    LC_ALL=C awk -v ret=1 '
      NF  {if ($1 ~ /^-/ && $2 == 0) ret=0; exit}
      END {exit(ret)}'
then
  printf '%s\n' "fd $fd is open on a regular file that has no link in the filessystem"
fi

Zde duplikování fd na 0 jako v předchozím řešení, takže to funguje, i když má fd příznak close-on-exec (za předpokladu, že fd není na prvním místě 0, ale fd 0 by normálně neměl příznak close-on-exec vlajka).

Tento druh přístupu nefunguje s falešným souborovým systémem, který je v Linuxu procfs pro kontrolu, zda se fd neotevře na /proc/<some-pid>/cmdline odkazuje na živý proces:

$ zsh -c 'zmodload zsh/stat; (sleep 1; stat -f0 +nlink; cat) < /proc/$$/cmdline &'
$ 1
cat: -: No such process

Podívejte se, jak fstat().st_nlink vrátil 1 výše (což by znamenalo, že soubor měl stále odkaz na adresář), zatímco cat 's read() na fd vrátil chybu. To není obvyklá sémantika souborového systému.

V každém případě, abyste zjistili, zda váš rodič stále běží, můžete zavolat na číslo getppid() který by vrátil 1 nebo pid podřízeného subreaperu, kdyby rodič zemřel. V zsh , použijete $sysparams[ppid] (v zsh/system modul).

$ sh -c 'zsh -c '\''zmodload zsh/system
                    print $PPID $sysparams[ppid]
                    sleep 2; print $PPID $sysparams[ppid]
                '\'' & sleep 1'
14585 14585
$ 14585 1

V bash , můžete použít ps -o ppid= -p "$BASHPID" místo toho.

Dalším přístupem by bylo vytvořit rouru mezi rodičem a potomkem a zkontrolovat pomocí select /poll (nebo read -t0 v bash ), že je stále aktivní.

Lze to provést pomocí coproc (pouze nedávno přidáno do bash ) namísto & .

background_with_pipe() {
  coproc "[email protected]" {PARENT_FD}<&0 <&3 3<&- >&4 4>&-
} 3<&0 4>&1

parent_gone() {
  local ignore
  read -t0 -u "$PARENT_FD" ignore
}

background_with_pipe eval '
  parent_gone || echo parent still there
  sleep 2
  parent_gone && echo parent gone
'

sleep 1
exit

Které dávají:

$ bash ./that-script
parent still there
$ parent gone

Navazovat na svůj předpokládaný přístup a znovu předpokládat linuxové jádro s procfs připojeno na /proc , můžete také udělat:

exec {PARENT_CANARY}< /proc/self/cmdline; PARENT_PID=$BASHPID
parent_gone() {
  ! [[ /proc/$PARENT_PID/cmdline -ef /proc/self/fd/$PARENT_CANARY ]]
}

(
   parent_gone || echo parent still there
   sleep 2
   parent_gone && echo parent gone
) &

sleep 1

Pomocí [[ file1 -ef file2 ]] které zkontrolují, zda i tyto soubory mají stejné číslo dev a inode (st_dev a st_ino vráceno stat() ).

Zdá se, že to funguje s 5.6.0, ale jak jsme viděli výše, /proc nectí obvyklou sémantiku souborového systému, nemohu zaručit, že je bez ras (PID a číslo inodu mohly být znovu použity) nebo že bude fungovat v budoucích verzích Linuxu.


Váš původní soubor existuje zcela beze změny.

Jakmile je soubor otevřen podle názvu, deskriptor souboru, který váš proces obsahuje, se počítá jako odkaz na soubor. Systém neuvolní soubor ani jeho prostor, dokud nejsou smazány všechny odkazy:může to být libovolný počet procesů, které mají otevřený popis souboru, plus libovolný počet pevných odkazů.

Můžete uvést soubor v době, kdy byl otevřen, a aktuální soubor uvést podle názvu. Pokud se jedná o různé inody nebo jiné datum modifikace, máte smazaný soubor a existuje nový soubor. Nebo můžete zjistit, že máte smazaný soubor, ale žádný nový neexistuje.


Linux
  1. Může být Bash skript připojen k souboru?

  2. Bash Script:Zkontrolujte, zda je soubor textovým souborem?

  3. Jak zkontrolovat syslog v Bash na Linuxu?

  1. Jak zkontrolovat syntaxi sudoers

  2. The Bash ‘?

  3. Jak zkontrolovat, zda je soubor prázdný v Bash?

  1. Jak zkontrolovat průběh běhu Cp?

  2. Jak zkontrolovat podřetězec v Shell Script Bash?

  3. Obnovit smazaný soubor??