ksh93
có các quy tắc thường được sử dụng cho loại điều này. Với zsh
, bạn có thể chiếm quyền điều khiển các thư mục động đặt tên tính năng :
Xác định ví dụ:
zsh_directory_name() {
case $1 in
(n)
case $2 in
(incr) reply=($((++incr)))
esac
esac
}
Và sau đó bạn có thể sử dụng ~[incr]
để tăng dần $incr
mỗi lần:
$ echo ~[incr]
1
$ echo ~[incr] ~[incr]
2 3
Cách tiếp cận của bạn không thành công bởi vì head -1 /tmp/ints
, đầu mở fifo, đọc một bộ đệm đầy đủ, in một dòng và sau đó đóng nó . Sau khi đóng lại, kết thúc bằng văn bản nhìn thấy một đường ống bị hỏng.
Thay vào đó, bạn có thể làm:
$ 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
Ở đó, chúng tôi để kết thúc đọc mở trên fd 3 và read
đọc một byte mỗi lần, không phải là bộ đệm đầy đủ để đảm bảo đọc chính xác một dòng (tối đa ký tự dòng mới).
Hoặc bạn có thể làm:
$ 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
Thời gian đó, chúng tôi khởi tạo một đường ống cho mọi giá trị. Điều đó cho phép trả về dữ liệu chứa bất kỳ số lượng dòng tùy ý.
Tuy nhiên, trong trường hợp đó, ngay khi cat
mở fifo, echo
vòng lặp và vòng lặp được bỏ chặn, do đó echo
có thể chạy nhiều hơn , đến lúc cat
đọc nội dung và đóng đường ống (khiến đường tiếp theo echo
khởi tạo một đường ống mới).
Một công việc xung quanh có thể là thêm một số độ trễ, ví dụ như bằng cách chạy một bên ngoài echo
như được đề xuất bởi @jimmij hoặc thêm một số sleep
, nhưng điều đó vẫn sẽ không mạnh mẽ, hoặc bạn có thể tạo lại đường ống được đặt tên sau mỗi lần echo
:
while
mkfifo $fifo &&
echo $((++incr)) > $fifo &&
rm -f $fifo
do : nothing
done &
Điều đó vẫn để lại các cửa sổ ngắn nơi đường ống không tồn tại (giữa unlink()
được thực hiện bởi rm
và mknod()
được thực hiện bởi mkfifo
) gây ra cat
lỗi và các cửa sổ rất ngắn nơi đường ống đã được khởi tạo nhưng không có quá trình nào sẽ ghi lại vào đó (giữa write()
và close()
được thực hiện bởi echo
) gây ra cat
không trả lại gì, và các cửa sổ ngắn nơi đường ống được đặt tên vẫn tồn tại nhưng không có gì sẽ mở nó để viết (giữa close()
được thực hiện bởi echo
và unlink()
được thực hiện bởi rm
) nơi cat
sẽ treo.
Bạn có thể loại bỏ một số cửa sổ bằng cách thực hiện như sau:
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
) &
Theo cách đó, vấn đề duy nhất là nếu bạn chạy nhiều con mèo cùng một lúc (tất cả chúng đều mở fifo trước khi vòng lặp viết của chúng tôi sẵn sàng mở nó để viết) trong trường hợp chúng sẽ chia sẻ echo
đầu ra.
Tôi cũng khuyên bạn không nên tạo tên cố định, fifos có thể đọc được trên thế giới (hoặc bất kỳ tệp nào cho vấn đề đó) trong các thư mục có thể ghi trên thế giới /tmp
trừ khi đó là dịch vụ được hiển thị cho tất cả người dùng trên hệ thống.