如何使用锁机制从不同的脚本写入文件



我想实现以下目标:

  • 一个脚本连续地将传感器结果写入文件
  • 另一个并发运行的脚本每秒读取文件,锁定文件,平均文件中的所有值,使其为空文件,然后解锁它,以便前面提到的脚本再次将传感器结果写入该文件

我正在使用Bourne shell脚本,这是到目前为止的补丁解决方案,它结合了我在网上找到的解决方案。我想知道一些关于我目前拥有的东西,也欢迎任何改进的建议。

while :
do
(
flock -x 2
echo $SENSOR_1_VALUE | tee -a sensor1.txt
)2> sensor1lockfile
done

和平均脚本:

#every 1s:
(
flock -x 2
awk '{ total += $1; count++ } END { print total/count }' sensor1.txt
# empty the file
> sensor1.txt
) 2> sensor1lockfile

现在,最终我将有大约10个传感器,它们都有自己的文件sensor1…Sensor10 ect和平均脚本将每秒钟对所有这些脚本进行平均,并将这些平均值发送到另一个子系统。

这可能是非常愚蠢的,但我试图使sensor1.txt取代上述两个脚本中的sensor1lockfile,这没有工作。理想情况下,我不希望有20个文件(10个用于每个传感器的值,10个用于锁定目的),因此我试图仅使用值文本文件作为锁定文件。

我也听说subshell进程的()对于性能来说不是理想的,我在这里有什么替代方案?我还注意到,超过9的fd数字对sh不起作用,这就是我需要使用的…这本身可能是我的应用程序的一个问题。

任何帮助,建议或输入将不胜感激,谢谢。

您可以简化:

while :; do
flock -x 1
echo "$sensorvalue"
flock -u 1
done >>"$sensorfile"
while sleep 1; do
flock -x 0
awk '{ total+=$1; count++ } END{ print total/count }' "$sensorfile"
>"$sensorfile"
flock -u 0
done <"$sensorfile"

如果您真的想使用shell脚本解决这个问题,我认为您实际上非常接近。我会重写"传感器读数"。脚本看起来像这样:

#!/bin/bash
values="sensor$1.txt"
lockfile="sensor$1.lock"
# See comments on this answer for why this might be
# a bad idea.
#trap 'rm -f $lockfile' EXIT
while :; do
(
flock -x 3
echo $(( RANDOM % 10 )) >> "$values"
)3> "$lockfile"
sleep 0.5
done

将设备编号作为输入参数,因此我们只需要一个脚本用于N传感器。它会在退出时自动清理锁定文件。这里我使用$RANDOM伪造传感器值,您当然会将此代码替换为实际读取传感器的东西。

要创建每个传感器的平均值,我们可以只遍历sensor*.txt文件,像这样:

#!/bin/bash
while :; do
for values in sensor*.txt; do
lockfile="${values/.txt/.lock}"
(
flock -x 3
awk -vVALUES="$values" '{ total += $1; count++ } END { printf "%s avg (%d): %fn", VALUES, count, total/count }' "$values"
: > "$values"
) 3> "$lockfile"
done
sleep 1
done
我通过启动10个假传感器来测试这些,像这样:
$ for i in {1..10}; do sh startsensor.sh $i & done
...
$ jobs
[1]   Running                 sh startsensor.sh $i &
[2]   Running                 sh startsensor.sh $i &
[3]   Running                 sh startsensor.sh $i &
[4]   Running                 sh startsensor.sh $i &
[5]   Running                 sh startsensor.sh $i &
[6]   Running                 sh startsensor.sh $i &
[7]   Running                 sh startsensor.sh $i &
[8]   Running                 sh startsensor.sh $i &
[9]-  Running                 sh startsensor.sh $i &
[10]+  Running                 sh startsensor.sh $i &
$ ls
calc_average.sh  sensor1.txt   sensor3.txt   sensor5.txt   sensor7.txt   sensor9.txt
sensor10.lock    sensor2.lock  sensor4.lock  sensor6.lock  sensor8.lock  startsensor.sh
sensor10.txt     sensor2.txt   sensor4.txt   sensor6.txt   sensor8.txt
sensor1.lock     sensor3.lock  sensor5.lock  sensor7.lock  sensor9.lock
当这些脚本运行时,calc_average.sh脚本产生如下输出:
sensor10.txt avg (11): 5.181818
sensor1.txt avg (11): 3.909091
sensor2.txt avg (10): 3.800000
sensor3.txt avg (10): 2.700000
sensor4.txt avg (10): 4.000000
sensor5.txt avg (10): 3.100000
sensor6.txt avg (10): 4.100000
sensor7.txt avg (10): 3.900000
sensor8.txt avg (10): 4.700000
sensor9.txt avg (10): 4.700000

请注意,我使用fd 3而不是3作为lockfile,这样我们就不会抑制stderr输出(这对识别错误很有用)。

最新更新