コマンドを実行すると、type type
stdoutの結果が表示されます。
次に、次のコマンドを試してみます。
type type > abc.txt
abc.txt
したがって、このコマンドが同じプロセス(bash自体)で実行されると、ファイル記述子1はポイントしますabc.txt
。abc.txt
にabc.txt
。
ただし、結果は常に標準出力として印刷されます。これは、シェルの組み込みがフォークされたプロセスで実行されていることを意味しますか?
答え1
通常、コマンドをリダイレクトするためにシェルがしなければならないのは、子プロセスをフォークして子プロセスだけにリダイレクトしてから(親ファイル記述子は影響を受けません)、その中でコマンドを実行することです(親は待っている間)。 。
組み込みコマンド(または複合コマンドまたは関数...)の場合、フォークや実行はありません。ただし、リダイレクトされた組み込みコマンドが終了すると、ファイル記述子は以前の状態に戻ります。
この目的のために、シェルはリダイレクトを実行する前に、リダイレクトされたファイル記述子のコピーを別のファイル記述子に保存し、そのファイル記述子をO_CLOEXECフラグとして表示します(組み込み機能が同じコマンドをeval
実行する場合command
)。返されると、シェルはファイル記述子を復元します。
たとえば、次のコマンドを実行すると、次のようになります。
strace sh -c 'echo test > /dev/null; :'
表示される内容(関連項目のみを含む):
open("/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
:リダイレクトするファイルを開きます。fcntl(1, F_DUPFD, 10) = 10
:生のstdoutを最初の利用可能なfd> = 10(ここでは10)にコピーします。fcntl(10, F_SETFD, FD_CLOEXEC) = 0
:O_CLOEXEC フラグを設定します。dup2(3, 1) = 1
:リダイレクトされたファイルを標準出力に設定します。close(3) = 0
:もう必要ありません。write(1, "test\n", 5) = 5
:echo は実行され、標準出力に "test\n" を書き込みます (現在 /dev/null にリダイレクトされます)。dup2(10, 1) = 1
: 標準出力の復元close(10) = 0
:不要になったfd 10を閉じます。
Bourneシェルで複合コマンドをリダイレクトすると、ブランチが発生します(thenにa=0; { a=1; echo "$a"; } >&2; echo "$a"
示されています)。この問題を解決するには、実際に上記の作業を手動で実行する必要があります。1
0
変える
while cmd1; do cmd2; i=`expr "$i" + 1`; done > file
あなたはこれをしなければなりません:
exec 3>&1 > file
while cmd1 3>&-; do cmd2 3>&-; i=`expr "$i" + 1 3>&-`; done
exec >&3 3>&-
( 3>&-
fd には O_CLOEXEC フラグがないため、各コマンドごとに 1 つずつ)
以前のバージョンのBourneシェルでは、組み込みコマンドをリダイレクトできませんでした。 pdp11をエミュレートするUnix V7では:
$ eval a=1 > /tmp/x
illegal io
$ read a < /etc/passwd
illegal io
答え2
出力リダイレクト
ファイル記述子は標準出力ストリームを1
表します。stdout
で出力リダイレクトを使用すると、type type > abc.txt
シェルは書き込み用にファイルを開き、ターミナルデバイスではなく開いたファイルを指すようにabc.txt
ファイル記述子を変更します。1
ただし、このリダイレクトは次の場合にのみ機能します。現在のコマンド実行中なのでこれがいいえコマンドが分岐プロセス(またはサブシェル)で実行されることを意味します。
継続的なリダイレクト
リダイレクトを続行するには、exec
組み込みシェルを使用してファイル記述子を変更できます。たとえば、連続コマンドの標準出力をリダイレクトするには、次のコマンドを実行します。
exec >abc.txt
すべてのコマンド出力がターミナルデバイスの代わりにファイルにリダイレクトされると、シェルセッションを使用するのは難しいので、このコマンドを実行するときは注意してください。 (ファイル記述子)が指す同じ装置にファイル記述子をリダイレクトすることで、stdout
ファイル記述子を端末出力装置に復元することができます。stderr
2
exec >&2
関連リソース
詳細については、次を参照してください。
- 部分リダイレクトBashマニュアルから
- 入出力グレッグのwikiから
- チュートリアルリダイレクトBash-hackers Wikiから
- これリダイレクトウィキペディア記事
- これファイル記述子ウィキペディア記事
答え3
コマンドが完了すると、入力ファイルはすぐに閉じて他のプロセスから書き込むことができ、ファイル記述子が解放され、子プロセスが終了します。