ファイル記述子が有効かどうかをテストする

ファイル記述子が有効かどうかをテストする

bashスクリプトを開くときに3以上のファイル記述子(FD)に追加情報を出力したいです。 FDがオンになっているかどうかをテストするために、次のトリックを考案しました。

if (printf '' 1>&3) 2>&-; then
  # File descriptor 3 is open
else
  # File descriptor 3 is not open
fi

これは私の要件には十分ですが、FDが動作しているかどうかをテストするより慣用的な方法があるかどうか疑問に思います。私は特に、FDフラグの検索(およびFDが書き込み可能かどうかをテストし、FDを読み取ることができるかどうかをテストする)を可能にするfcntl(1)シェルコマンドへのシステムコールマッピングがあるかどうかに興味があります。O_WRONLYO_RDWRO_RDONLYO_RDWR

答え1

ksh(AT&Tおよびpdkshバリアント)では、zsh次のことができます。

if print -nu3; then
  echo fd 3 is writeable
fi

fdに何も書きませんが、fdが書き込み可能かどうかをfcntl(3, F_GETFL)確認し、それ以外の場合はエラーを報告します。

$ ksh -c 'print -nu3' 3< /dev/null
ksh: print: -u: 3: fd not open for writing

(にリダイレクトできます/dev/null)。

bash私はあなたの唯一のオプションはあなたの方法のようにfdが成功したことを確認することだと思います。しかし、これはfdが書き込み可能であることを保証するものではありません(またはそうするためにdup()外部ユーティリティ(zsh/ ...)を呼び出します)。perlfcntl()

(ほとんどのシェルと同様に)代わりにをbash使用すると、追加のプロセスが分岐します。あなたはそれを使用することができます:(...){...;}

if { true >&3; } 2> /dev/null

むしろ、ブランチを避けることです(複合コマンドをリダイレクトすると、常にサブシェルが生成されるBourneシェルを除く)。:代わりに使用しないでくださいtrue特別な組み込みのため、bashがPOSIX互換モードになっているとシェルは終了します。

ただし、次のように短縮できます。

if { >&3; } 2> /dev/null

答え2

POSIXではcommand アプリケーションの使い方説明は次のとおりです。

場合によっては、特殊な組み込み関数の特殊機能を抑制すると利点があります。たとえば、

command exec > unwritable-file

非対話型スクリプトを中断しないため、スクリプトを使用して出力状態を確認できます。

そのため、次のようにできます。

if    command >&3
then  echo 3 is open >&3
else  ! echo 3 is not open
fi    2<>/dev/null

または...

{ command >&3
  printf %s\\n%.0d  string "0$(($??8:0))" >&"$(($??1:3))"
} 2<>/dev/null

誰が書くことができますかひもstdout または 3 の ewline が続き、\n3 が開かないときにはまだゼロ以外の終了状態を渡します。なぜなら、完成した数学が$?最終的に8進数に変換されないからです。08到着%少数しかし、8進数をnullに切り捨てます。00

または...

command exec >&3 || handle_it

ただし、を使用している場合は、ksh93次のようにできます。

fds

開かれたファイル記述子のリスト。-l彼らがどこに行くのかを見るには追加してください。

答え3

開かれたファイル記述子は で見つけることができます/proc/<pid>/fd。たとえば、現在のシェルの開いているファイル記述子を一覧表示するには、ls -l /proc/$$/fd次のコマンドを実行できます。

total 0
lrwx------ 1 testuser testuser 64 jun  1 09:11 0 -> /dev/pts/3
lrwx------ 1 testuser testuser 64 jun  1 09:11 1 -> /dev/pts/3
lrwx------ 1 testuser testuser 64 jun  1 09:11 2 -> /dev/pts/3
lrwx------ 1 testuser testuser 64 jun  1 09:39 255 -> /dev/pts/3

以下を使用してファイルを開くとき:

touch /tmp/myfile
exec 7</tmp/myfile

newとしてリストする必要がありますls -l /proc/$$/fd

lr-x------ 1 testuser testuser 64 jun  1 09:11 7 -> /tmp/myfile

これを再度使用してファイル記述子を閉じると、exec 7>&-リストされなくなります/proc/$$/fd

答え4

この質問はかなり古い質問です。しかし、とにかく組み込み関数を使用するのはどうですか?

for i in {0..5} ; do if [ -t $i ]; then echo "$i is a valid FD"; else echo "$i is INVALID FD"; fi; done

出力:

0 is a valid FD
1 is a valid FD
2 is a valid FD
3 is INVALID FD
4 is INVALID FD
5 is INVALID FD

したがって、質問に答えるには、次のことをお勧めします。

if [ -t 3 ]; then
  # File descriptor 3 is open
else
  # File descriptor 3 is not open
fi

関連情報