2017-01-12 23 views
3

ファイルディスクリプタが現在Bashで使用されているかどうかを確認するにはどうすればよいですか?たとえば、fd 3を読み書きして閉じるスクリプトがあるとします。Bashで次に使用可能なファイル記述子を見つけるには?

exec 3< <(some command here) 
... 
cat <&3 
exec 3>&- 

私は私のスクリプトを実行する前に設定されている可能性があり記述子のためのいくつかの他の目的に干渉していないよ確保するための最良の方法は何ですか?スクリプト全体をサブシェルに入れる必要がありますか?純粋bash

+0

'['または' [[['ファイル記述子を開く'をテストする[' ']オプションは表示されません。最も近いアプローチは、ファイルディスクリプタが端末に接続されているかどうかをテストする '-t number'です。数字を解釈するスクリプトを取得するのは地獄です。 '>&$ number'を使うことはできませんので、サブシェルなどで混乱させる必要があります。与えられたファイル記述子をテストするプログラムを書くのは難しくありませんが、任意の数を使うようにシェルスクリプトを生成するのは難しいかもしれません。したがって、ほとんどの人は気にしません。 –

答えて

6

、あなたは与えられたファイルディスクリプタ(この場合は3)が利用可能であるかどうかを確認するために、次のメソッドを使用することができます。

rco="$(true 2>/dev/null >&3; echo $?)" 
rci="$(true 2>/dev/null <&3; echo $?)" 
if [[ "${rco}${rci}" = "11" ]] ; then 
    echo "Cannot read or write fd 3, hence okay to use" 
fi 

これは基本的にあなたが読み取りまたは書き込みができるかどうかを試験することにより動作します与えられたファイルハンドル。あなたがどちらもすることができないと仮定すると、おそらく大丈夫です。そのスクリプトを実行する

exec 3>/dev/null # Testing, comment out to make 
exec 4</dev/null # descriptor available. 

found=none 
for fd in {0..200}; do 
    rco="$(true 2>/dev/null >&${fd}; echo $?)" 
    rci="$(true 2>/dev/null <&${fd}; echo $?)" 
    [[ "${rco}${rci}" = "11" ]] && found=${fd} && break 
done 
echo "First free is ${found}" 

最初の自由記述子として5を与えますが、あなたはどのように見てexecラインで遊ぶことができます:最初の自由記述をを見つけるの面で

、あなたのようなものを使用することができますより早いものを利用できるようにすると、コードスニペットがそれを見つけることができます。


としては、コメントで指摘し、procfsを提供するシステム(/procファイルシステム)は、彼らが自由記述子を検出することが可能な別の方法を持っています。次のように/proc/PID/fdディレクトリには、各オープンファイル記述子のエントリが含まれます:ちょうど保つ

exec 3>/dev/null # Testing, comment out to make 
exec 4</dev/null # descriptor available. 

found=none 
for fd in {0..200} ; do 
    [[ ! -e /proc/$$/fd/${fd} ]] && found=${fd} && break 
done 
echo "First free is ${found}" 

pax> ls -1 /proc/$$/fd 
0 
1 
2 
255 

だから、そこに自由なエントリを見つけるために、上記のものと同様のスクリプトを使用することができますbashを提供するすべてのシステムが必ずしもprocfs(BDSとCygWinが例です)を持つとは限りません。もしそれがあなたがターゲットとしているOSなら、Linuxでうまくいくはずです。もちろん


、あなたはようなものとして、あなたの全体のシェルスクリプトをラップするオプション持たまだやる:その場合は

(
    # Your current script goes here 
) 

を、ファイルハンドルは、それらの括弧とあなたの外に保存されますあなたが適切に見える範囲でそれらを操作することができます。

+1

同じようにパフォーマンスが良いですか?サブシェル・パフォーマンスのペナルティなしにこれを行う方法はありますか? (注意:bashのパフォーマンスには限界がありますが、一般的にサブシェルは可能な限り避けてください) – Kvass

+2

@Kvass、反復回数が多いループで*検出*をしない限り、違いはありません。 *リダイレクション*がループ内にあっても、ループが始まる前に*必要なフリーハンドルを検出し、ループ内のそれらの記述子を単に使用します。かなりのパフォーマンス上のペナルティはありません。 – paxdiablo

+0

'ls/proc/$$/fd'で提供されているリストにない番号を選択すると何が問題になりますか? – sorontar

3

ファイル記述子が9より大きいかどうか気にしない場合は、シェル自体にファイル記述子を提供するよう依頼することができます。もちろん、fdは自分自身のシェルによって自由になることが保証されています。 bashの4.1以降(2009年12月31日)実際には{varname} style automatic file descriptor allocation

$ exec {var}>hellofile 
$ echo "$var" 
15 

$ echo "this is a test" >&${var} 
$ cat hellofile 
this is a test 

$ exec {var}>&-      # to close the fd. 

以降で利用可能

機能は、Linuxでは、あなたがオープンFDSを見ることができます:

$ ls /proc/$$/fd 
0 1 2 255 
+0

私はこれを試してみると 'exec {my_var}'コマンドが見つかりません – Kvass

+0

この機能を動作させるには、最新のバッシュ4.1以上が必要です。 [{varname}スタイルの自動ファイル記述子の割り当て\t 4.1-alpha](http://wiki.bash-hackers.org/scripting/bashchanges) – sorontar

+0

私は4.4を実行しています – Kvass

5

他の答えていますpre-bash-4を使用します。1構文は、不要なサブシェルの生成と冗長チェックを行います。それはまた、最大FD数に対して任意のカットオフを有する。

次のコードでは、サブシェルの生成なしで(FD番号の適切な上限値を取得する場合は、ulimitコール以外の)トリックを行う必要があります。

fd=2 max=$(ulimit -n) 

while ((++fd < max)); do 
    ! true <&$fd && break 
done 2>&- && echo $fd 
  • 我々はだますことができない1に達するまで、基本的に私たちは可能なFDを反復処理します。
  • Bad file descriptorエラーメッセージを回避するために、whileコマンド全体のstderrを閉じます。
関連する問題