ksh93
この種のものに通常使用される分野があります。を使用するzsh
と、動的な名前付きディレクトリ機能を乗っ取ることができます。
たとえば、次のように定義します。
zsh_directory_name() {
case $1 in
(n)
case $2 in
(incr) reply=($((++incr)))
esac
esac
}
そして、あなたは毎回~[incr]
インクリメントするのに使うことができます$incr
:
$ echo ~[incr]
1
$ echo ~[incr] ~[incr]
2 3
ではhead -1 /tmp/ints
、headがfifoを開き、バッファー全体を読み取り、1行を出力してから閉じるため、アプローチが失敗します。閉じられると、書き込み側には壊れたパイプが表示されます。
代わりに、次のいずれかを行うことができます。
$ 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
そこでは、fd 3で読み取り側を開いたままにして、read
バッファー全体ではなく、一度に1バイトを読み取り、正確に1行(改行文字まで)を読み取るようにします。
またはあなたがすることができます:
$ 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
そのとき、すべての値のパイプをインスタンス化します。これにより、任意の行数を含むデータを返すことができます。
ただし、その場合、cat
FIFO を開くとすぐにecho
、ループがブロック解除さecho
れるためcat
、コンテンツが読み取られてパイプが閉じられるまでに、さらにループが実行される可能性があります(次echo
を実行して新しいパイプをインスタンス化します)。
echo
回避策としては、たとえば@jimmijで提案されているように外部を実行するなどの遅延を追加するか、を追加することができますsleep
が、それでも非常に堅牢ではないか、それぞれの後に名前付きパイプを再作成できますecho
。
while
mkfifo $fifo &&
echo $((++incr)) > $fifo &&
rm -f $fifo
do : nothing
done &
それはまだ(の間のパイプが存在しない短い窓の葉unlink()
によって行わrm
及びmknod()
によって行わmkfifo
引き起こす)cat
が失敗すると、間(パイプがインスタンス化されていますが、どのプロセスが今までそれを再度書き込みをしません非常に短い窓write()
とclose()
行わecho
引き起こす)cat
何も返さないために、名前付きパイプがまだ存在しますが、何が今まで(の間で書き込み用に開きません短い窓close()
によって行わecho
及びunlink()
によって行われrm
ている)cat
ハングしますが。
次のようにすることで、これらのウィンドウの一部を削除できます。
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
) &
このように、唯一の問題は、同時に複数の猫を実行する場合(書き込みループが書き込み用に開く準備ができる前に、すべてがfifoを開く場合)であり、その場合、それらはecho
出力を共有します。
また/tmp
、システム上のすべてのユーザーに公開されるサービスでない限り、世界中の書き込み可能なディレクトリに、固定名の世界中で読み取り可能なfifo(または問題のファイル)を作成しないこともお勧めします。