GNU/Linux >> Belajar Linux >  >> Linux

Membuat file temp vs substitusi proses vs ekspansi variabel?

<(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.


Linux
  1. Memfilter tcpdump:Membuat keteraturan dari kekacauan

  2. Panduan pemula untuk membuat pengalihan dalam file .htaccess

  3. Membuat file CSR sertifikat web.

  1. Bagaimana Cara Menentukan Proses Yang Membuat File??

  2. Mengapa Substitusi Proses Bash Tidak Bekerja Dengan Beberapa Perintah?

  3. Bagaimana Menunda Ekspansi Variabel?

  1. Proses Substitusi Output Out Of The Order?

  2. Membuat File Kosong Memiliki Nama Variabel Dalam Skrip?

  3. Substitusi variabel lingkungan di sed