<(cmd)
adalah ksh
fitur juga ditemukan saat ini di zsh
dan bash
disebut substitusi proses .
Pada sistem yang mendukung /dev/fd/n
atau /proc/self/fd/n
, ini diimplementasikan dengan pipa dan jika tidak dengan pipa bernama sementara. Bagaimanapun, itu adalah bentuk pipa yang merupakan mekanisme komunikasi antarproses.
cmd1 <(cmd2)
Dapat ditulis (dengan pipa normal):
{ cmd2 4<&- | 3<&0 <&4 4<&- cmd1 /dev/fd/3; } 4<&0
Atau (dengan nama pipa):
mkfifo /tmp/named_pipe
cmd2 > /tmp/named_pipe & cmd1 /tmp/named_pipe
Artinya, kedua perintah dijalankan secara bersamaan dan berkomunikasi dengan sebuah pipa. Anda biasanya menggunakan cmd2 | cmd1
untuk itu, tetapi substitusi proses biasanya untuk kasus-kasus di mana cmd1
hanya dapat mengambil input dari nama file dan bukan dari input standar atau ketika diperlukan lebih dari satu input seperti di diff <(cmd1) <(cmd2)
.
Tidak ada batas yang mempengaruhinya selain yang umum seperti jumlah proses, waktu cpu, atau memori.
PIPEBUF dilaporkan oleh beberapa implementasi ulimit
seperti bash
dan beberapa implementasi dari ksh
bukan rlimit tetapi ukuran maksimum yang menulis ke pipa dijamin atom jadi tidak relevan di sini. Ukuran pipa itu sendiri (64kB di Linux seperti yang dilaporkan oleh @dsmsk80) sebenarnya bukan batasan itu sendiri. Itu hanya mengatakan sebanyak cmd2
dapat menulis ke pipa bahkan setelah cmd1
telah berhenti membacanya.
Namun ada batasan dalam cmd1
itu hanya boleh membaca dari berkas itu. Karena berupa pipa, ia tidak dapat menulis ke file tersebut atau mencari bolak-balik di dalam file.
zsh
memiliki substitusi perintah bentuk ketiga menggunakan file sementara biasa:
cmd1 =(cmd2)
memanggil cmd1
dengan file sementara yang berisi keluaran cmd2
. Dalam hal ini cmd1
dijalankan setelah cmd2 bukannya secara bersamaan. Batas ukuran file dapat dicapai di sana.
Saya tidak tahu ada Shell yang mengimplementasikan <<<(...)
operator. Namun ada <<<
operator di zsh
(terinspirasi dari operator yang sama di port Unix rc
) juga ditemukan di ksh93
versi terbaru dan bash
. Ini adalah variasi dari <<
operator heredoc memanggil herestring.
Di:
cmd <<< something
Yang sama dengan standar:
cmd << EOF
something
EOF
Shell membuat file sementara dengan something\n
sebagai konten dan memasukkannya sebagai input standar ke proses baru, memutuskan tautan file itu dan mengeksekusi cmd
dalam proses baru itu. Sekali lagi, itu adalah file biasa sehingga batas maksimum ukuran file dapat tercapai.
Sekarang Anda dapat menggabungkan <<<
operator dengan $(...)
(substitusi perintah) entah bagaimana meniru zsh
=(...)
operator di bash
dan ksh93
:
cmd1 <<<"$(cmd2)"
Akan menjalankan cmd2
dengan itu stdout dialihkan ke pipa. Di ujung pipa yang lain, shell membaca keluaran dari cmd2
dan menyimpannya dikurangi karakter baris baru yang tertinggal dan dengan satu karakter baris baru ditambahkan ke file sementara dan panggil cmd1
dengan file sementara itu terbuka untuk dibaca sebagai stdin (perhatikan ada batasan lain yang tidak akan berfungsi jika cmd2
keluaran berisi karakter NUL).
Menjadi seperti =(...)
, Anda harus menulisnya:
cmd1 /dev/fd/3 3<<<"$(cmd3)"
Perhatikan bahwa shell harus membaca seluruh output cmd3 di memori sebelum menulisnya ke file sementara, jadi selain ukuran file maksimum, Anda juga dapat mencapai batas penggunaan memori.
Perhatikan juga bahwa sejak versi 5, bash
menghapus izin menulis ke file sementara sebelum memanggil cmd1
, jadi jika Anda memerlukan cmd1
untuk dapat memodifikasi file itu, Anda harus mengatasinya dengan:
{
chmod u+w /dev/fd/3 && # only needed in bash 5+
cmd1 /dev/fd/3
} 3<<<"$(cmd3)"
Substitusi proses Bash dalam bentuk <(cmd)
dan >(cmd)
diimplementasikan dengan pipa bernama jika sistem mendukungnya. Perintah cmd
dijalankan dengan input/outputnya terhubung ke pipa. Saat Anda menjalankan mis. cat <(sleep 10; ls)
Anda dapat menemukan pipa yang dibuat di bawah direktori /proc/pid_of_cat/fd
. Pipa bernama ini kemudian diteruskan sebagai argumen ke perintah saat ini (cat
).
Kapasitas buffer pipa dapat diperkirakan dengan penggunaan dd
yang rumit perintah yang mengirim data nol ke input standar sleep
perintah (yang tidak melakukan apa-apa). Rupanya, prosesnya akan tidur beberapa saat sehingga buffer akan penuh:
(dd if=/dev/zero bs=1 | sleep 999) &
Tunggu sebentar lalu kirim USR1
sinyal ke dd
proses:
pkill -USR1 dd
Ini membuat proses untuk mencetak statistik I/O:
65537+0 records in
65536+0 records out
65536 bytes (66 kB) copied, 8.62622 s, 7.6 kB/s
Dalam kasus pengujian saya, ukuran buffer adalah 64kB
(65536B
).
Bagaimana Anda menggunakan <<<(cmd)
ekspansi? Saya mengetahui bahwa ini adalah variasi dari dokumen di sini yang diperluas dan diteruskan ke perintah pada input standarnya.
Mudah-mudahan, saya menjelaskan pertanyaan tentang ukuran. Mengenai kecepatan, saya tidak begitu yakin, tetapi saya berasumsi bahwa kedua metode tersebut dapat memberikan throughput yang serupa.