Bashですべてのファイル記述子を閉じます。

Bashですべてのファイル記述子を閉じます。

あらかじめ明示的にリストせずに開いているすべてのファイル記述子を閉じる方法はありますか?

答え1

文字通り答え、閉じるみんなファイル記述子を開くbash:

for fd in $(ls /proc/$$/fd); do
  eval "exec $fd>&-"
done

しかし、これはシェルの入力と出力に必要なデフォルトのファイル記述子を閉じるので、実際には良い考えではありません。これにより、実行しているすべてのプログラムは、ttyデバイスに直接書き込まない限り、端末に出力を表示しません。実際に私がテストした結果stdinexec 0>&-)を閉じると、対話型シェルは終了しました。

実際に行うことは、デフォルトのシェル操作の一部ではないすべてのファイル記述子を閉じることです。これらはstdin0、1、2stdoutですstderr。これに加えて、一部のシェルは基本的に別のファイル記述子を開くようです。bashたとえば、255(端末I / Oにも使用されます)がありますが、dash私の場合は10です。これは、/dev/tty端末が使用する特定のtty/ deviceではないことを示します。pts0、1、2、255を除くすべての項目をオフにするには、次の手順を実行しますbash

for fd in $(ls /proc/$$/fd); do
  case "$fd" in
    0|1|2|255)
      ;;
    *)
      eval "exec $fd>&-"
      ;;
  esac
done

これは、変数に含まれるファイル記述子をリダイレクトするときにもeval必要です。それ以外の場合、bash変数は拡張されますが、コマンドの一部として処理されます(この場合は、execコマンド0または1記述子を閉じたいすべてのファイルを試してください)。

メモ:lsまた、(例えば)の代わりにglobを使用すると、glob用の追加の/proc/$$/fd/*ファイル記述子が開かれているように見えるため、lsここでは最良の解決策のようです。

修正する

移植性の詳細については、/proc/$$/fd次を参照してください。ファイル記述子リンクの移植性。ご利用できない場合は/proc/$$/fd代替品(使用可能な場合)を差し上げます。$(ls /proc/$$/fd)lsof$(lsof -p $$ -Ff | grep f[0-9] | cut -c 2-)

答え2

最新バージョンのBash(4.1以降、2009以降)ではできるシェル変数を使用して閉じるファイル記述子を指定します。

for fd in $(ls /proc/$$/fd/); do
    [ $fd -gt 2 ] && exec {fd}<&-
done

この機能はKornシェル(1993年から?)にありましたが、Bashに適用されるまでに少し時間がかかったようです。

答え3

現在、シェルのi / o / eを除くすべてのファイル記述子を消去しますが、引数として指定されたファイル記述子は含まれていません。

clear_fds() {
for fd in $(compgen -G "/proc/$BASHPID/fd/*"); do
    fd=${fd/*\/}
        if [[ ! " $* " =~ " ${fd} " ]]; then
            case "$fd" in
                0|1|2|255)
                ;;
                *)
                    eval "exec $fd>&-"
                    ;;
            esac
        fi
done
}

答え4

カント。カーネルは一度に 1 つの FD だけを閉じることができ、bash には FD の「グループコマンド」はありません。

for fd in $(ls -1 /proc/27343/fd); do echo exec $fd">&"-; done

echoそしてテスト後に取り外します"

シェル自体ではなくコマンドを実行する場合はnohup

関連情報