我想使用纯文本文件作为我的应用程序的任务队列(用于写入数据库,尽管这是无关紧要的),其中:
echo "some task" >> task_queue.txt
对于2.如果我在多个线程或进程中访问/修改task_queue.txt
,我不知道如何避免竞争条件。以下不是原子的:
ITEM=`head -1 task_queue.txt`
sed -i '1d' task_queue.txt
# process the item in the application
Bash是否提供了比使用锁定文件更优雅的方法?我之前从未使用过flock
因此我不知道这是否很混乱(例如,当我的应用程序的任务处理失败时)。
答案 0 :(得分:1)
所有这些都受到竞争条件的影响,在检查文件是否被访问以及对文件进行操作之间。虽然大概是检查和操作之间的时间非常短。
一种方法是使用-f
和if ! pgrep -f task_queue.txt &>/dev/null; then
## File not Open, do stuff
else
## File is Open, do stuff
fi
选项匹配完整命令行,如果文件匹配则匹配,即访问该文件的任何进程。这假设该过程没有修改它的命令行。
这可以做到:
lsof
另一种方法包括解析fuser
或/proc/PID/fd/*
(这与解析if ! lsof /path/to/task_queue.txt &>/dev/null; then
## File not Open, do stuff
else
## File is Open, do stuff
fi
相同):
fuser
同样if ! fuser /path/to/task_queue.txt &>/dev/null; then
## File not Open, do stuff
else
## File is Open, do stuff
fi
:
lsof
请注意,这里我们将fuser
/ /dev/null
的STDOUT和STDERR发送到lsof
,这可能并不总是可取的,因为可能存在一些警告/错误,并且因为我们仅依赖于退出状态,所有这些都将被错误处理,因为文件正在使用中。如果fuser
/ 1
针对不同的事件具有不同的退出状态,则会更容易实现,但我可以看到styles.xml
针对每种类型的失败或不匹配。
答案 1 :(得分:0)
虽然我不能确认它是原子的,但它比我自己写的任何东西(可能)都要原子化得多,并且对于我的非任务关键型应用来说已经足够了:
sed -i -e '1 w /dev/stdout' -e '1d' task_queue.txt