GNU/Linux >> Belajar Linux >  >> Linux

Cara Portabel (posix) Untuk Mencapai Substitusi Proses?

Beberapa shell, seperti bash , mendukung Proses Substitusi yang merupakan cara untuk menampilkan output proses sebagai file, seperti ini:

$ diff <(sort file1) <(sort file2)

Namun, konstruksi ini bukan POSIX dan, karenanya, tidak portabel. Bagaimana proses substitusi dapat dicapai dengan cara yang ramah POSIX (yaitu yang berfungsi di /bin/sh ) ?

catatan:pertanyaannya bukan menanyakan bagaimana membedakan dua file yang diurutkan – itu hanya contoh yang dibuat-buat untuk mendemonstrasikan proses substitusi!

Jawaban yang Diterima:

Fitur itu diperkenalkan oleh ksh (pertama didokumentasikan dalam ksh86) dan menggunakan /dev/fd/n fitur
(ditambahkan secara independen di beberapa BSD dan sistem AT&T sebelumnya).
Dalam ksh dan hingga ksh93u, itu tidak akan berfungsi kecuali sistem Anda memiliki dukungan untuk /dev/fd/n . zsh, bash dan ksh93u+ dan di atasnya dapat menggunakan pipa bernama sementara (pipa bernama ditambahkan di Sistem III) di mana /dev/fd/n tidak tersedia.

Pada sistem di mana /dev/fd/n tersedia (POSIX tidak menentukannya),
Anda dapat melakukan substitusi proses (mis., diff <(cmd1) <(cmd2) ) sendiri dengan:

{
  cmd1 4<&- | {
    # in here fd 3 points to the reading end of the pipe
    # from cmd1, while fd 0 has been restored from the original
    # stdin (saved on fd 4, now closed as no longer needed)

    cmd2 3<&- | diff /dev/fd/3 -

  } 3<&0 <&4 4<&- # restore the original stdin for cmd2

} 4<&0 # save a copy of stdin for cmd2

Namun itu tidak berfungsi dengan ksh93 di Linux seperti di sana, pipa shell diimplementasikan dengan socketpairs bukan pipa dan membuka /dev/fd/3 di mana fd 3 menunjuk ke soket tidak berfungsi di Linux.

Meskipun POSIX tidak menentukan /dev/fd/n , itu menentukan pipa bernama. Pipa bernama berfungsi seperti pipa normal kecuali Anda dapat mengaksesnya dari sistem file. Masalahnya di sini adalah Anda harus membuat yang sementara dan membersihkan setelahnya, yang sulit dilakukan dengan andal, terutama mengingat POSIX tidak memiliki mekanisme standar (seperti mktemp -d seperti yang ditemukan pada beberapa sistem) untuk membuat file atau direktori sementara, dan penanganan sinyal (untuk membersihkan saat hang-up atau mematikan) juga sulit dilakukan secara portabel.

Anda dapat melakukan sesuatu seperti:

tmpfifo() (
  n=0
  until
    fifo=$1.$$.$n
    mkfifo -m 600 -- "$fifo" 2> /dev/null
  do
    n=$((n + 1))
    # give up after 20 attempts as it could be a permanent condition
    # that prevents us from creating fifos. You'd need to raise that
    # limit if you intend to create (and use at the same time)
    # more than 20 fifos in your script
    [ "$n" -lt 20 ] || exit 1
  done
  printf '%s\n' "$fifo"
)

cleanup() { rm -f -- "$fifo"; }

fifo=$(tmpfifo /tmp/fifo) || exit

cmd2 > "$fifo" & cmd1 | diff - "$fifo"

cleanup

(tidak mengurus penanganan sinyal di sini).

Terkait:Proses selesai segera setelah membuka Terminal dan tidak mungkin menambahkan perintah?
Linux
  1. Proses Induk Baru Ketika Proses Induk Meninggal?

  2. Nilai Maksimum Id Proses?

  3. Linux – Cara Portabel Untuk Mendapatkan Alamat Sumber Rute Default?

  1. Proses Substitusi Output Out Of The Order?

  2. Cara Tercepat Untuk Mengekstrak Iso?

  3. Apakah ada cara untuk mengubah variabel lingkungan dari proses lain di Unix?

  1. Apa cara terbaik untuk mengirim sinyal ke semua anggota grup proses?

  2. Apa definisi sesi di linux?

  3. Cara secara terprogram mengambil GID dari proses yang sedang berjalan