GNU/Linux >> Linux の 問題 >  >> Linux

ファイル記述子が削除されたファイルを参照しているかどうかを確認します (Bash で)

ファイル記述子が、ファイル システムのどのディレクトリにもリンクが残っていない通常のファイルを参照しているかどうかをテストするには、fstat() を作成します。 その上でシステムコールを呼び出し、リンクの数を確認します (st_nlink

zsh で 、あなたはその stat でそれを行うことができます 組み込み:

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 シェル) には同等のものはありませんが、GNU システムを使用している場合は、GNU stat を使用している可能性があります。 その場合、次のようなことができるはずです:

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

OS カーネルが Linux の場合、より移植性の高いアプローチ (zsh を持たない OS の場合) proc ファイルシステムが /proc にマウントされていることを前提としています。 ls を使用する可能性があります /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

ここでは、前のソリューションのように 0 で fd を複製するため、fd に close-on-exec フラグがある場合でも機能します (そもそも fd が 0 ではないと仮定しますが、fd 0 には通常 close-on-exec フラグがありません)。フラグ)

この種のアプローチは、fd が /proc/<some-pid>/cmdline で開いているかどうかを確認する Linux の procfs である偽のファイルシステムでは機能しません。 ライブ プロセスを指します:

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

fstat().st_nlink のやり方を見る cat の間、上記の 1 が返されました (これは、ファイルがまだディレクトリへのリンクを持っていることを意味します)。 の read() fd でエラーが返されました。これは、通常のファイル システム セマンティックではありません。

いずれにせよ、親がまだ実行中かどうかを確認するには、getppid() を呼び出します。 親が死んだ場合、1または子サブリーパーのpidを返します。 zsh で 、 $sysparams[ppid] を使用します (zsh/system で モジュール)

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

bash で 、 ps -o ppid= -p "$BASHPID" を使用できます

別のアプローチは、親と子の間にパイプを作成し、 select でチェックすることです /poll (または read -t0 bash で ) まだ稼働中です。

coproc を使用して実行できます (最近 bash に追加されたばかりです ) & の代わりに .

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

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

想定したアプローチを構築し、再び procfs の Linux カーネルを想定 /proc に搭載 、次のこともできます:

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

[[ file1 -ef file2 ]] の使用 too ファイルが同じ dev および inode 番号 (st_dev) を持っているかどうかをチェックします。 と st_ino stat() によって返されます ).

これは 5.6.0 で動作するようですが、上記で見たように /proc 通常のファイルシステムのセマンティクスを尊重しません。競合がないこと (PID と inode 番号が再利用された可能性があります) や、将来の Linux バージョンで動作することを保証できません。


元のファイルはまったく変更されずに存在します。

ファイルが名前で開かれると、プロセスが保持するファイル記述子はファイルへのリンクとしてカウントされます。すべてのリンクが削除されるまで、システムはファイルまたはそのスペースを解放しません。それらは、ファイルの説明が開いている任意の数のプロセスと、任意の数のハード リンクである可能性があります。

ファイルを開いた時点で stat し、現在のファイルを名前で stat することができます。それらが異なる i ノードまたは異なる変更日である場合、削除されたファイルがあり、新しいファイルがあります。または、ファイルが削除されているのに、新しいファイルが存在しないことに気付くかもしれません。


Linux
  1. sudoers構文を確認する方法

  2. Bashスクリプトをファイルに接続できますか?

  3. Cpの実行の進行状況を確認する方法は?

  1. シェルスクリプトBashでサブストリングをチェックする方法は?

  2. 削除されたファイルを回復しますか?

  3. Linux の Bash で syslog を確認するには?

  1. バッシュ‘?

  2. Bashスクリプト:ファイルがテキストファイルかどうかを確認しますか?

  3. Bashでファイルが空かどうかを確認するには?