如何读取被多次覆盖的文件?
How to read a file that's been overwritten multiple times?
我有一个 bash 脚本,它会尽可能快地不断截取屏幕截图,通常每个 运行 需要 1-2 毫秒。
我还想有一个单独的进程,运行不断地在另一个线程上运行,它将获取所述屏幕截图文件并对它们进行一些处理(裁剪、读取等)。
有时我可以 运行 并排就好了,但有时进程 B 试图读取进程 A 仍在写入的文件。
如何解决这个问题?
我想像 cache/copy/buffer 这样的东西会有帮助,但我不确定。
我想起了文件锁,它们正是我需要的。
在截取屏幕截图时,我将使用带有共享锁的 UNIX flock (with an exclusive lock) and while reading the files I will use Ruby's File#flock。
应该这样做!
我制作了几个简单的文件,它们在控制齐射之前和之后做一些事情——在这种情况下,只报告循环中的哪个文件在哪个点,所以我只是将它符号链接到第二个名字。我称他们为a & b。
$: cat a
for a in 1 2 3
do echo "[=10=] $a before: $(date)"
kill -CONT -1 # NOTE: sends the signal to ALL procs in group
kill -STOP $$
echo "[=10=] $a AFTER: $(date)"
done
kill -CONT -1
b 是同一个文件,只是另一个名称。
运行 两者都有。最后用一个wait
清理一下提示。
$: ./a;./b;wait
./a 1 before: Mon, Aug 10, 2020 12:56:41 PM
[1]+ Stopped ./a
./b 1 before: Mon, Aug 10, 2020 12:56:41 PM
[2]+ Stopped ./b
./a 1 AFTER: Mon, Aug 10, 2020 12:56:41 PM
./a 2 before: Mon, Aug 10, 2020 12:56:41 PM
[1]+ Stopped ./a
./b 1 AFTER: Mon, Aug 10, 2020 12:56:41 PM
./b 2 before: Mon, Aug 10, 2020 12:56:41 PM
[2]+ Stopped ./b
./a 2 AFTER: Mon, Aug 10, 2020 12:56:41 PM
./a 3 before: Mon, Aug 10, 2020 12:56:41 PM
[1]+ Stopped ./a
./b 2 AFTER: Mon, Aug 10, 2020 12:56:42 PM
./b 3 before: Mon, Aug 10, 2020 12:56:42 PM
[2]+ Stopped ./b
./a 3 AFTER: Mon, Aug 10, 2020 12:56:42 PM
[1]- Done ./a
./b 3 AFTER: Mon, Aug 10, 2020 12:56:42 PM
[2]+ Done ./b
这会向 stderr 抛出大量垃圾,但您可以将其重定向。
$: { ./a;./b;wait; } >log 2>err
也许它会提供一些灵感。
解决此问题的最简单方法是将文件写入同一驱动器上的不同文件夹中,或使用不同的扩展名,以便您可以轻松地将其从选择中排除(例如,而不是 images/foo.jpg
, 写入 images/foo.jpg.temp
, 并用 *.jpg
) 列出,然后在完成时使用原子移动 (mv images/foo.jpg.temp images/foo.jpg
).
我有一个 bash 脚本,它会尽可能快地不断截取屏幕截图,通常每个 运行 需要 1-2 毫秒。
我还想有一个单独的进程,运行不断地在另一个线程上运行,它将获取所述屏幕截图文件并对它们进行一些处理(裁剪、读取等)。
有时我可以 运行 并排就好了,但有时进程 B 试图读取进程 A 仍在写入的文件。
如何解决这个问题?
我想像 cache/copy/buffer 这样的东西会有帮助,但我不确定。
我想起了文件锁,它们正是我需要的。
在截取屏幕截图时,我将使用带有共享锁的 UNIX flock (with an exclusive lock) and while reading the files I will use Ruby's File#flock。
应该这样做!
我制作了几个简单的文件,它们在控制齐射之前和之后做一些事情——在这种情况下,只报告循环中的哪个文件在哪个点,所以我只是将它符号链接到第二个名字。我称他们为a & b。
$: cat a
for a in 1 2 3
do echo "[=10=] $a before: $(date)"
kill -CONT -1 # NOTE: sends the signal to ALL procs in group
kill -STOP $$
echo "[=10=] $a AFTER: $(date)"
done
kill -CONT -1
b 是同一个文件,只是另一个名称。
运行 两者都有。最后用一个wait
清理一下提示。
$: ./a;./b;wait
./a 1 before: Mon, Aug 10, 2020 12:56:41 PM
[1]+ Stopped ./a
./b 1 before: Mon, Aug 10, 2020 12:56:41 PM
[2]+ Stopped ./b
./a 1 AFTER: Mon, Aug 10, 2020 12:56:41 PM
./a 2 before: Mon, Aug 10, 2020 12:56:41 PM
[1]+ Stopped ./a
./b 1 AFTER: Mon, Aug 10, 2020 12:56:41 PM
./b 2 before: Mon, Aug 10, 2020 12:56:41 PM
[2]+ Stopped ./b
./a 2 AFTER: Mon, Aug 10, 2020 12:56:41 PM
./a 3 before: Mon, Aug 10, 2020 12:56:41 PM
[1]+ Stopped ./a
./b 2 AFTER: Mon, Aug 10, 2020 12:56:42 PM
./b 3 before: Mon, Aug 10, 2020 12:56:42 PM
[2]+ Stopped ./b
./a 3 AFTER: Mon, Aug 10, 2020 12:56:42 PM
[1]- Done ./a
./b 3 AFTER: Mon, Aug 10, 2020 12:56:42 PM
[2]+ Done ./b
这会向 stderr 抛出大量垃圾,但您可以将其重定向。
$: { ./a;./b;wait; } >log 2>err
也许它会提供一些灵感。
解决此问题的最简单方法是将文件写入同一驱动器上的不同文件夹中,或使用不同的扩展名,以便您可以轻松地将其从选择中排除(例如,而不是 images/foo.jpg
, 写入 images/foo.jpg.temp
, 并用 *.jpg
) 列出,然后在完成时使用原子移动 (mv images/foo.jpg.temp images/foo.jpg
).