file - 防止两个或多个 awk 实例同时写入同一个文件
问题描述
awk 是否有任何内置支持来防止写入另一个 awk 实例已经写入的同一文件?
考虑以下:
$ # Create large input file
$ for i in {1..500000}; do echo "$i,$i,$i" >> /tmp/LargeFile.txt; done
$ # Launch two simultaneous instances of awk outputting to the same file
$ awk -F"," '{print $0}' /tmp/LargeFile.txt >> /tmp/OutputFile.txt & awk -F"," '{print $0}' /tmp/LargeFile.txt >> /tmp/OutputFile.txt &
$ # Find out how many fields are in each line (ideally 3)
$ awk -F"," '{print NF}' /tmp/Output.txt | sort | uniq -c
1 0
553 1
1282 2
996412 3
1114 4
638 5
因此,两个 awk 实例同时将大量数据输出到同一个文件。理想情况下,输出文件的每行应包含三个逗号分隔值,但由于两个实例同时写入同一个文件,因此有些行可能有超过 3 个逗号分隔值,而有些则少于 3 个。
示例损坏的输出文件:
1,1,1 < 1's from from first instance of awk
2,2,2 < 2's from from first instance of awk
3,3,3 < 3's from from first instance of awk
1,1,1 < 1's from from second instance of awk
2,2,2 < 2's from from second instance of awk
4,4,4 < 4's from from first instance of awk
5,5,5 < 5's from from first instance of awk
3,3,3 < 3's from from second instance of awk
4,6,6,4,6 < corrupted input as both instances tried to write to this line at the same time
4
7,7,7 < 7's from from first instance of awk
有什么好的和简单的方法来防止这种情况吗?
编辑 - 从实际场景中添加更多细节:
每个 awk 实例所做的处理将更像这样:来自其他进程的数据被连续写入文件,例如每 5 分钟有一个新文件。将调用多个 awk 实例以按设定的时间间隔(例如每 30 分钟)处理/聚合数据。
cat SomeFilesWithLotsOfData | awk '
{
# process lots of data which takes a lot of time
# build up associate arrays based on input
}
END {
# Output processed data which takes little time
# Loop over associative arrays and output to persistent files
}'
假设处理部分(在 END 语句之前)需要 30 分钟才能完成(哇,那是很长的时间,但我们用它来说明一下)。可以实例化同一 awk 脚本的第二个实例,以在第一个实例结束之前处理带有数据的新批次文件,并且它需要将其处理后的数据输出到与前一个实例相同的文件中。每个 awk 实例输出到的输出文件的确切数量取决于输入(即,它基于输入记录中的特定字段)。我不想在处理输入之前锁定所有可能的输出文件,因为我不知道哪个 awk 实例将首先完成处理。所以目前我打算在 END 的开头创建一个锁并在 END 之后解锁它,但是我的实现有点笨拙,所以我
解决方案
在 Quick-and-dirty way 有一个类似的问题,以确保一次只运行一个 shell 脚本实例
flock(1)
如果您的系统上存在该命令,则该解决方案可能是最简单的。
一种选择是简单地包装awk 脚本的所有调用:
flock -x /var/lock/myscriptlockfile awk ...
这将序列化 awk 脚本的调用,以便一次只能运行一个。如果您想决定是稍后重试还是跳过,您可以调整flock
呼叫,使其在一段时间后终止,而不是永远等待。
要允许脚本的多个副本运行,但一次只允许一个副本,您可以调整此解决方案以flock
从您的 END 中调用,以使用以下内容包装所谓的“关键部分”:
awk 300>/var/lock/myscriptlockfile '
# ...
END {
system("flock -x 300");
# critical section
system("flock -u 300");
}
'
推荐阅读
- apache-kafka - 当应用程序没有完成偏移提交时kafka流应用程序的行为(并且自动提交关闭)
- c - 如果我使用 execl() 运行它,如何获得 /bin/ls -R 的返回值?
- jwt - 当 secretOrKey 不可用时在 Nestjs 中使用 JwtStrategy
- c++ - 单例模式 - 共享库中的符号和动态加载
- flutter - 你如何在颤振中添加一张卡片?
- sql - 加入 3 个表,从 2 个不同的表和按材料名称分组的总数量
- python - 展开页面顶部的画布
- javascript - 如何使用 fetch 在本地 json 文件中发布?
- amazon-redshift - Redshift中的存储过程不显示任何内容
- javascript - 如何比较javascript中的两个对象数组并更新值?