ksh93
memiliki disiplin ilmu yang biasanya digunakan untuk hal semacam ini. Dengan zsh
, Anda dapat membajak fitur direktori bernama dinamis :
Tentukan misalnya:
zsh_directory_name() {
case $1 in
(n)
case $2 in
(incr) reply=($((++incr)))
esac
esac
}
Dan kemudian Anda dapat menggunakan ~[incr]
untuk mendapatkan peningkatan $incr
setiap kali:
$ echo ~[incr]
1
$ echo ~[incr] ~[incr]
2 3
Pendekatan Anda gagal karena dalam head -1 /tmp/ints
, kepala membuka fifo, membaca buffer penuh, mencetak satu baris, dan kemudian menutupnya . Setelah ditutup, ujung tulisan melihat pipa rusak.
Sebaliknya, Anda bisa melakukan:
$ fifo=~/.generators/incr
$ (umask 077 && mkdir -p $fifo:h && rm -f $fifo && mkfifo $fifo)
$ seq infinity > $fifo &
$ exec 3< $fifo
$ IFS= read -rneu3
1
$ IFS= read -rneu3
2
Di sana, kami membiarkan ujung bacaan terbuka pada fd 3, dan read
membaca satu byte pada satu waktu, bukan buffer penuh untuk memastikan untuk membaca tepat satu baris (hingga karakter baris baru).
Atau Anda bisa melakukannya:
$ fifo=~/.generators/incr
$ (umask 077 && mkdir -p $fifo:h && rm -f $fifo && mkfifo $fifo)
$ while true; do echo $((++incr)) > $fifo; done &
$ cat $fifo
1
$ cat $fifo
2
Waktu itu, kami instantiate pipa untuk setiap nilai. Itu memungkinkan pengembalian data yang berisi jumlah garis sembarang.
Namun, dalam kasus itu, segera setelah cat
membuka fifo, echo
loop dan tidak terbuka, sehingga lebih banyak yang echo
dapat dijalankan, pada saat cat
membaca konten dan menutup pipa (menyebabkan berikutnya echo
instantiate pipa baru).
Pekerjaan di sekitar dapat menambahkan beberapa penundaan, seperti misalnya dengan menjalankan eksternal echo
seperti yang disarankan oleh @jimmij atau menambahkan beberapa sleep
, tapi itu masih belum terlalu kuat, atau Anda bisa membuat ulang pipa bernama setelah masing-masing echo
:
while
mkfifo $fifo &&
echo $((++incr)) > $fifo &&
rm -f $fifo
do : nothing
done &
Itu masih menyisakan jendela pendek di mana pipa tidak ada (antara unlink()
dilakukan oleh rm
dan mknod()
dilakukan oleh mkfifo
) menyebabkan cat
kegagalan, dan jendela sangat pendek di mana pipa telah dipakai tetapi tidak ada proses akan pernah menulis lagi untuk itu (antara write()
dan close()
dilakukan oleh echo
) menyebabkan cat
tidak menghasilkan apa-apa, dan jendela pendek di mana pipa bernama masih ada tetapi tidak akan pernah membukanya untuk menulis (antara close()
dilakukan oleh echo
dan unlink()
dilakukan oleh rm
) di mana cat
akan menggantung.
Anda dapat menghapus beberapa jendela dengan melakukannya seperti:
fifo=~/.generators/incr
(
umask 077
mkdir -p $fifo:h && rm -f $fifo && mkfifo $fifo &&
while
mkfifo $fifo.new &&
{
mv $fifo.new $fifo &&
echo $((++incr))
} > $fifo
do : nothing
done
) &
Dengan begitu, satu-satunya masalah adalah jika Anda menjalankan beberapa kucing secara bersamaan (mereka semua membuka fifo sebelum loop penulisan kami siap membukanya untuk menulis) dalam hal ini mereka akan membagikan echo
hasilnya.
Saya juga menyarankan untuk tidak membuat nama tetap, fifos yang dapat dibaca dunia (atau file apa pun yang penting) di direktori dunia yang dapat ditulisi seperti /tmp
kecuali jika itu adalah layanan yang akan diekspos kepada semua pengguna pada sistem.