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.