すでに遅れがあなたのセンサデータを収集していますが、フリッカーの要因であってもよいし、他の表示おかしなを引き起こす可能性があるものは何でもによって引き起こされることが指摘されています。
ここでは最小限の形でこれを代替する方法を示します。
#!/usr/bin/env/ bash
# This generates random sensor data and stores it in predictably named temp files,
# after a short random delay.
function gather() {
while sleep $(($RANDOM % 3)); do
printf '%2d\n' $(($RANDOM % 100)) > /tmp/t.$$.$1
done
}
main() {
# Background our data gatherers...
gather i &
gather j &
# Print a couple of blank lines, since our format starts with "up"
printf '\n\n'
# and loop.
while sleep 1; do
# gather our randomly generated sensor data...
i=$(< /tmp/t.$$.i)
j=$(< /tmp/t.$$.j)
# and print it.
printf "$fmt" "$i" "$j"
done
}
cleol=$(tput el)
up2=$(tput cuu1; tput cuu1)
fmt="${up2}Measurement 1: %d${cleol}\nMeasurement 2: %d${cleol}\n"
main
カーソル移動が楽しいです。 :-)
しかし、すべての点では、あなたの出力を書く責任があるループは非常に軽量です。それは静的テキストファイルからデータを取得し、印刷します。その後、繰り返します。すべての重い持ち上げは、バックグラウンドのgather()
関数で行われます。この関数は、ディスプレイの更新頻度とは異なる頻度でテキストファイルを更新します。
書かれているように、「書き込み」が起きている間ではなく、データが書き込まれる前に、「読み込み」がファイルに当たる可能性のある競合状態があることに注意してください。それを最小限に抑えるために、あなたはこのようなものでレースを回避することができます:
function gather() {
while sleep 1; do
value=$(
# This simulates the delay of a slow sensor read.
sleep $(($RANDOM % 3))
printf '%2d\n' $(($RANDOM % 100))
)
printf '%d\n' "$value" > /tmp/t.$$.$1
done
}
これには、優れている、と「十分」であってもよいが、このような一時ファイルへの書き込みはアトミックファイルシステムの操作ではありません競合状態の可能性は依然として存在する。
以下のバリエーションでは、データの読み込み中に長い遅延をシミュレートしますが、読み込みコマンドの出力は、別の一時ファイルに移動し、センサ読み込みの完了時にシンボリックリンクします。
function gather() {
local n=0 item="${1//[^[:alnum:]]/}"
while :; do
old="$(readlink /tmp/t.$$.$item)"
(
# This simulates the delay of a slow sensor read.
sleep $(($RANDOM % 3))
printf '%d\n' $(($RANDOM % 100))
) > /tmp/t.$$.$item.$n
test -s /tmp/t.$$.$item.$n &&
ln -sfn /tmp/t.$$.$item.$n /tmp/t.$$.$item &&
test -f "$old" &&
rm -f "$old"
((n++))
sleep 1
done
}
カッコ内のすべては、センサー出力を生成するために実行するものです。 $n
の値が不足するのを恐れている場合(ただし、陽子減衰を恐れることはありません)、増分カウンタを使用する代わりに$RANDOM
に切り替えることができます。
監視しているものは何でも、既存のモンタージュシステムを使用することを考えましたか?このような問題はすでに解決されているように思えます。 :-)
UPDATE ...
そして、私はよく私の時間を使用していないという理由だけで、ここに改善main()
機能やスクリプトの残りの部分です:
function main() {
# Background our data gatherers...
local -a pids=()
for thing in "${things[@]}"; do
gather $thing &
pids+=($!); echo "Backgrounded $thing at $!"
done
trap "echo 'Quitting...'; kill $(printf '%s ' "${pids[@]}"); exit 0" 2
trap "echo 'Aborting...'; kill $(printf '%s ' "${pids[@]}"); exit 1" 1 3 15
# Wait for gatherers to have at least one round of data
sleep 2
# and loop.
local -A v=()
while sleep 1; do
# gather our randomly generated sensor data...
for thing in "${things[@]}"; do
v[$thing]=$(< /tmp/t.$$.$thing)
done
# and print it.
printf "$fmt" "${v[@]}"
done
}
things=(i j) # the list of things to monitor
cleol=$(tput el) # you know what this is already
up2=$(tput cuu1; tput cuu1) # this too
fmt="${up2}Measurement 1: %d${cleol}\nMeasurement 2: %d${cleol}\n"
main
これは、モニターされた項目のリストを必要に応じてbash配列$things[]
と背景に置きます。エラーをトラップし、適切に切断します。それがしない1つのことは、$fmt
を配列のサイズに適合させることです。またはコーヒーを作る。
これは、あなたの2番目のアプローチで説明しているちらつきを引き起こす可能性があることを認識しています。私のためのものはありませんが、それは端末エミュレータによって異なる場合があります。 –
$ RANDOMの時間が非常に短いので、ちらつきはありません。実際に通信速度の遅い通信線やネットワークを介して測定値を返す外部デバイスに実際にアクセスしている場合は、新しいデータを取得する前にブランクが目立つように点滅する可能性があります。また、 'tput cuu $ i'は' i''tput cuu1'sを実行するのと同じですが、少し速いです。 'tput cuu $ iを使うことができます。 tput ed'を使って '$ i'行を上に移動し、(各行を順に空白にする代わりに)画面の最後までクリアしますが、私はまだ私のバージョンを好みます。 – rici
@rici良い点、私は更新します。 (そして私はあなたの解決策も気に入っています;)) –