同じファイルにエコーされる2つのスクリプトが並列に実行されています。あるスクリプトは+++++++++++++++
ファイルをエコーし、もう一方のスクリプトはファイルを===========
エコーします。
以下は最初のスクリプトです。
#!/bin/bash
while [ 1==1 ];
do
echo "+++++++++++++++" >> log.txt
# commands
done
2番目のスクリプトは次のとおりです。
#!/bin/bash
while [ 1==1 ];
do
echo "===========" >> log.txt
# commands
done
log.txtファイルは約1,400,000行を印刷しますが、1行でも++==のような混同される大文字がありませんか?
Linuxはこの混乱を防ぐことができますか?もしそうなら、どうしてそしてなぜ?
答え1
簡単に言えば、このecho
コマンドはwrite
アトミックシステムコールをトリガーします。
write
指定されたすべてのバイトが書き込まれる保証はありませんが、この場合(データが少ない)には書き込まれます。
その後、理論的にはバイトwrite(fd, buffer, n)
より少なく書き込み、n
プログラムがバイトを書き込むことができるように書き込まれた実際のバイト数を返すことができますbuffer+n
。
パイプには無制限の容量がないため、パイプでこれが発生する可能性があります。
~からwrite(2)
O_APPEND(2)を使用してファイルを開くと、ファイルオフセットは書き込み前に最初にファイルの終わりに設定されます。ファイルオフセットの調整と書き込みは、アトミックステップで実行されます。
POSIX.1 によれば、count が SSIZE_MAX より大きい場合、結果は実装に従って定義されます。 Linuxの上限の説明を参照してください。
答え2
次の制限を試すことができます。
#!/bin/bash
outer() {
rm log.txt
inner() {
a=$(perl -e 'print "'$1'"x'$2'')
while [ 1==1 ];
do
echo $a >> log.txt
# commands
done
}
export -f inner
timeout 5 bash -c "inner '-' $1" &
timeout 5 bash -c "inner '+' $1" &
wait
sort -u log.txt
}
replace_repeats() {
# Replace
# ---
# with
# -3
perl -pe 's/((.)\2+)/"$2".length$1/e'
}
# This is OK
outer 10 | replace_repeats
outer 100 | replace_repeats
outer 1000 | replace_repeats
outer 4095 | replace_repeats
# This breaks.
# It should give:
# +4096
# -4096
outer 4096 | replace_repeats