通常,当用 Bash 解释软件开发概念时,我比用 JavaScript 解释得更好。
关于检查时间到使用时间(TOCTOU),它在维基百科当前的开头段落:
在软件开发中,检查时间到使用时间(TOCTOU、TOCTTOU 或 TOC/TOU)是一类由竞争条件引起的软件错误,涉及系统部分状态的检查(例如安全凭证)以及该检查结果的使用。
Bash 中的简单或简单的检查时间到使用时间场景是什么?
答案1
我在本网站上看到的该类型最常见的竞争条件与进程 ID (PID) 的处理以及基于这些的信号发送有关。
有人可能会使用ps
+grep
来获取某个命名进程的 PID,然后kill
向其发出信号。在获取 PID 和发送信号之间,PID 可能已经消失。使用pkill
可以最大限度地减少此错误发生的窗口。
在其他情况下,保留 PID 并期望它在较长时间内始终引用同一进程(例如,在“PID 文件”中)可能会导致信号发送到错误的进程。这是因为所有 Unix 系统都重用 PID。
另一个常见问题是文件锁定,即使用文件系统为多进程同步和临界区提供锁定机制。例如,可以测试某个“锁定文件”是否存在,如果不存在,则创建它并从而“获取锁定”。在检查文件存在和创建锁定文件之间,其他进程也有机会意识到锁定文件不存在:
while [ -e "$lockfile" ]; do
sleep 10
done
touch "$lockfile"
echo 'got lock' # or did I?
# do work
rm -f "$lockfile"
解决方案在这情况是使用专用的文件锁定工具,例如flock
,或使用锁目录,因为mkdir
是原子的:
while ! mkdir "$lockdir" 2>/dev/null; do
sleep 10
done
echo 'got lock'
# do work
rmdir "$lockdir"
这在 NFS 等网络文件系统上仍然无法可靠地工作,因为这些系统不提供目录创建的原子操作。
无疑还有很多其他的例子。