
私が次のようなことをしていたら
一時ファイルの作成
some process generating output > temp_file cat temp_file
プロセスの交換:
cat <(some process generating output)
他の方法:
cat <<<(some process generating output)
これについていくつかの質問があります。
<()
>()
プロセス置換や変数拡張のためのデータ出力サイズに制限はありますか?<<<()
- 次のうち最も速いものは何ですか?それとももっと速くする方法はありますか?
私のulimitコマンドの出力は次のとおりです。
bash-3.00$ ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
open files (-n) 256
pipe size (512 bytes, -p) 10
stack size (kbytes, -s) 8480
cpu time (seconds, -t) unlimited
max user processes (-u) 8053
virtual memory (kbytes, -v) unlimited
答え1
<(cmd)
またksh
今は、zsh
bash
プロセスの交換。
/dev/fd/n
または をサポートするシステムでは、/proc/self/fd/n
一時的な名前付きパイプではなくパイプを介して実装されます。とにかく、それはプロセス間通信メカニズムであるパイプの形です。
cmd1 <(cmd2)
(通常のパイプを使用して)次のように書くことができます。
{ cmd2 4<&- | 3<&0 <&4 4<&- cmd1 /dev/fd/3; } 4<&0
または(名前付きパイプを使用):
mkfifo /tmp/named_pipe
cmd2 > /tmp/named_pipe & cmd1 /tmp/named_pipe
つまり、両方のコマンドが同時に開始され、パイプと通信します。通常、これを実行しますcmd2 | cmd1
が、プロセス置換は標準入力ではなくファイル名からのみ入力を取得できcmd1
ますdiff <(cmd1) <(cmd2)
。
プロセス数、CPU 時間、メモリなどの一般的な制限に加えて、他の制限は影響しません。
ulimit
PIPEBUFのいくつかの実装と同様のbash
レポートでは、PIPEBUFksh
はrlimitではありませんが、パイプへの書き込みが原子的に保証される最大サイズであるため、これには関係ありません。パイプ自体のサイズ(Linuxでは@dsmsk80が64kBを報告する)自体は実際に制限ではありません。cmd2
パイプから読み取りを中断した後もパイプに書き込むことができると言います。cmd1
cmd1
しかし、読むこのファイルから。パイプなので、ファイルに書き込んだり、ファイルを前後に表示したりすることはできません。
zsh
通常の一時ファイルを使用する3番目の形式のコマンド置換があります。
cmd1 =(cmd2)
cmd1
呼び出しは、出力を含む一時ファイルで行われますcmd2
。この場合cmd1
実行後ろに同時代わりにcmd2。ファイルサイズ制限に達する可能性があります。
<<<(...)
私は演算子を実装するシェルを知りません。しかし、(Unixポートの同じ演算子からインスピレーションを得た)<<<
演算子は、およびの最新バージョンでも見つかります。zsh
これはherestringと呼ばれるheredoc演算子のバリアントです。rc
ksh93
bash
<<
存在する:
cmd <<< something
標準と同じ:
cmd << EOF
something
EOF
シェルは一時ファイルをsomething\n
コンテンツとして生成し、それを新しいプロセスに標準入力として提供し、ファイルのリンクを解除してcmd
新しいプロセスで実行します。繰り返しますが、これは通常のファイルなので、最大ファイルサイズ制限に達する可能性があります。
これで、<<<
演算子を(コマンドの置き換え)と組み合わせて、任意$(...)
の方法で演算子をエミュレートできますzsh
。=(...)
bash
ksh93
cmd1 <<<"$(cmd2)"
cmd2
パイプにリダイレクトされた標準出力として実行されます。パイプのもう一方の端では、シェルは出力を読み取り、末尾の改行をcmd2
除いて保存し、一時ファイルに改行を追加し、その一時ファイルを呼び出してcmd1
stdinで読み取るために開きます(別の制限があることに注意してください)にNUL文字が含まれていると機能しませんcmd2
。
ようになるには、=(...)
次のように書く必要があります。
cmd1 /dev/fd/3 3<<<"$(cmd3)"
シェルは一時ファイルに書き込む前にメモリ内のcmd3の出力全体を読み取る必要があるため、最大ファイルサイズに加えてメモリ使用量の制限に達することがあります。
また、バージョン 5 以降では、bash
呼び出し前に一時ファイルへの書き込み権限が削除されるため、ファイルを変更する必要があるcmd1
場合は、cmd1
次の方法で問題を解決する必要があります。
{
chmod u+w /dev/fd/3 && # only needed in bash 5+
cmd1 /dev/fd/3
} 3<<<"$(cmd3)"
答え2
<(cmd)
Bashプロセスの交換は、>(cmd)
システムが名前付きパイプをサポートしている場合に実装されます。コマンドはcmd
パイプに接続された入出力で実行されます。たとえば、実行すると、cat <(sleep 10; ls)
ディレクトリで作成されたパイプラインを見つけることができます/proc/pid_of_cat/fd
。この名前付きパイプは、現在のコマンド(cat
)にパラメータとして渡されます。
パイプのバッファ容量は、コマンドの標準入力にゼロデータを送信する(何もしない)dd
コマンドを賢く使用して推定できます。sleep
明らかに、プロセスはバッファがいっぱいになるようにしばらくスリープ状態になります。
(dd if=/dev/zero bs=1 | sleep 999) &
しばらく待ってからUSR1
プロセスに信号を送信しますdd
。
pkill -USR1 dd
これにより、プロセスはI / O統計を印刷します。
65537+0 records in
65536+0 records out
65536 bytes (66 kB) copied, 8.62622 s, 7.6 kB/s
私のテストケースでは、バッファサイズは64kB
(65536B
)です。
拡張機能はどのように使用しますか<<<(cmd)
?私はこれが拡張され、標準入力のコマンドに渡されるドキュメントのバリエーションであることを知っています。
サイズに関する問題を明らかにできることを願っています。速度についてはわかりませんが、どちらの方法も同様のスループットを提供すると仮定します。