【发布时间】:2018-11-23 17:12:00
【问题描述】:
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 之后解锁它,但是我的实现有点笨拙,所以我正在寻找一种更好的方法。
【问题讨论】:
-
可能有一些方法可以防止这种情况发生。 1-
awk2- 让第一个命令完成,然后它会自动进入第二个命令,然后你的文件将被连接起来。 2-如果您想在后台运行它们,则使用不同的输出文件,一旦它们完成,然后将它们连接起来或将它们写入同一个文件中。如果有人对您有帮助,请告诉我? -
感谢 RavinderSingh13。我不能保证这两个 awk 进程不会同时运行,我希望避免在最后连接文件的额外复杂性(在我的实际场景中实现起来很复杂)。所以我希望 awk 可能有一些不错的内置功能。
-
正如已经建议的那样,您为什么不编写 2 个不同的文件,然后简单地
cat将它们转换为 1 个输出?老实说,这样做不会有任何混淆。 -
您不能只使用
sem或pidlock来确保只有一个awk实例正在运行吗?否则你可以在文件上使用锁来避免冲突:lockfile命令可以帮助你 -
写入多个文件然后将它们连接起来的困惑在于,实际上每个 awk 实例可能正在写入的输出文件数量不定。在我的示例中只有两个,但实际上每个 awk 实例会有很多,并且每个文件都需要保护。 awk 如何使用 lockfile 来保护文件?