web-dev-qa-db-ja.com

Bashタブ補完が不要なファイルシステム情報を読み取るように見える?

/ nfs_shareにNFS共有がマウントされたNFSクライアントがあるとします。

NFSサーバーのプラグを抜いて、異常なシャットダウンが発生したとします。

現在、クライアントの/ nfs_shareは古くなっています。

クライアントでbashプロンプトに移動してls /nfs_<TAB>と入力すると、bashシェルがフリーズします。 syscallでスタックしているようです。

「/ nfs_」に一致する可能性のあるエントリを検索するために/を読み取るだけでは、/ nfs_shareにマウントされたNFSファイルシステムのエントリではなく、/ファイルシステムのエントリを読み取るため、応答しないファイルシステムではブロックされません。

フリーズは、タブの補完によってbash(またはその他の何か)がNFS F/Sのプロパティを読み取る場合にのみ発生します。

それで、NFSファイルシステムに何が当たっているのかを誰かが知っているなら、私は負傷しますか?そして、文字列照合を行ってタブ補完を行うときにマウントされたファイルシステムのプロパティを読み取らないようにシステムを構成できますか?

過去(数年前)に、おそらく別のディストリビューションで、古いNFSマウントにヒットすると、エラーメッセージとゼロ以外の終了コードが生成され、すぐにそれが発生したことを覚えています。

*)私にとってこの動作は、systemdの一部がファイルシステム情報をキャッシュすることによって「最適化」しようとしているように感じます。もしそうなら、OK-しかし、どうすればオフにできますか?

1
emerth

Bashでの完了は2段階のプロセスです-一部の部分はbashによって行われ、一部はreadlineによって行われます。ファイル名補完の場合、bashはディレクトリエントリのリストを取得してから、ファイル名をreadlineに渡します。ここで、 にあります

mark-directories
on」に設定すると、完成したディレクトリ名にスラッシュが追加されます。デフォルトは「on」です。

次に statsファイル名 を読み、スラッシュを追加するかどうかを決定します。一部のシステムでは、一部のファイルシステムでは、bashがディレクトリエントリを取得したときにこの情報がすでに利用可能ですが、常にそうであるとは限りません。

いずれにせよ、strace -o log bashset mark-directories offの有無にかかわらず.inputrcを簡単に確認すると、これが主な理由である可能性が高いことがわかります。

set mark-directories offなし:

read(0, "\t", 1)                        = 1
openat(AT_FDCWD, "/", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC|O_DIRECTORY) = 3
fstat64(3, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
getdents64(3, /* 20 entries */, 32768)  = 488
getdents64(3, /* 0 entries */, 32768)   = 0
close(3)                                = 0
write(2, "\n", 1)                       = 1
stat64("/bin", {st_mode=S_IFDIR|0755, st_size=53248, ...}) = 0
stat64("/bin", {st_mode=S_IFDIR|0755, st_size=53248, ...}) = 0
stat64("/boot", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat64("/boot", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
write(2, "bin/  boot/ \n", 13)          = 13
write(2, "bash-5.0$ ls /b", 15)         = 15

と:

read(0, "\t", 1)                        = 1
openat(AT_FDCWD, "/", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC|O_DIRECTORY) = 3
fstat64(3, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
getdents64(3, /* 20 entries */, 32768)  = 488
getdents64(3, /* 0 entries */, 32768)   = 0
close(3)                                = 0
write(2, "\n", 1)                       = 1
write(2, "bin   boot  \n", 13)          = 13
write(2, "bash-5.0$ ls /b", 15)         = 15
2
muru

これは、NFSマウントがクライアントによって処理される方法が原因です。はリモート接続のように扱われ、クライアントはls要求をリモートNFSホストに送信し、応答を待ちます。 timeoオプションを設定して指定されたタイムアウト期間内またはデフォルトのタイムアウト期間(60秒)内に応答がない場合、クライアントはNFS要求を再試行するため、シェルプロンプトはビジー状態で待機し続けます。応答のため。

NFS共有のエントリがfstabに存在するため、この動作は予期されたものです。押すと、完了が(NFS共有がすでにマウントされているため)からです Tab この場合、systemdまたはbashに固有の接続はありません。

これらのオプションsoft,bg存在します。 NFSshareをクライアントにマウントするときに使用してみてください。また、timeo=30オプションのデフォルトのタイムアウトは600(60秒)なので、短くすることをお勧めします。

ソフト/ハード

NFS要求がタイムアウトした後のNFSクライアントの回復動作を決定します。どちらのオプションも指定されていない場合(またはhardオプションが指定されている場合)、NFS要求は無期限に再試行されます。ソフトオプションが指定されている場合、NFSクライアントは、再送信再送信が送信された後にNFS要求に失敗し、NFSクライアントが呼び出し元のアプリケーションにエラーを返します。

bg/fg

エクスポートのマウントに失敗した場合のmount(8)コマンドの動作を決定します。 fgオプションを指定すると、マウント要求のいずれかの部分がタイムアウトするか、完全に失敗した場合、mount(8)はエラーステータスで終了します。これは「フォアグラウンド」マウントと呼ばれ、fgとbgのどちらのマウントオプションも指定されていない場合のデフォルトの動作です。

詳細は [〜#〜] nfs [〜#〜] を参照してください。

2
Raffa