python中的原子'ln-sf'(符号链接覆盖exsting文件)
我想创建一个符号链接,如果需要,覆盖现有文件或符号链接 我发现,对于未断开的符号链接,只返回python中的原子'ln-sf'(符号链接覆盖exsting文件),python,atomic,symlink,Python,Atomic,Symlink,我想创建一个符号链接,如果需要,覆盖现有文件或符号链接 我发现,对于未断开的符号链接,只返回True,所以我猜任何测试都必须包括 在python中实现ln-sf的最原子的方法是什么?(即,防止在删除和符号链接创建之间由另一个进程创建文件) 差异化:不指定原子要求此代码试图最小化竞争条件的可能性: import os import tempfile def symlink_force(target, link_name): ''' Create a symbolic link
True
,所以我猜任何测试都必须包括
在python中实现ln-sf
的最原子的方法是什么?(即,防止在删除和符号链接创建之间由另一个进程创建文件)
差异化:不指定原子要求此代码试图最小化竞争条件的可能性:
import os
import tempfile
def symlink_force(target, link_name):
'''
Create a symbolic link link_name pointing to target.
Overwrites link_name if it exists.
'''
# os.replace() may fail if files are on different filesystems
link_dir = os.path.dirname(link_name)
while True:
temp_link_name = tempfile.mktemp(dir=link_dir)
try:
os.symlink(target, temp_link_name)
break
except FileExistsError:
pass
try:
os.replace(temp_link_name, link_name)
except OSError: # e.g. permission denied
os.remove(temp_link_name)
raise
注:
temp\u link\u name
上创建的符号链接可以在替换link\u name
之前由另一个进程修改os.symlink()
问题
归功于。如果您准备了
ln-s文件tmplink
,那么mv tmplink
是原子链接。@Amadan感谢您的建议。我仍然看到了一个安全漏洞,但我希望我在中得到了尽可能好的安全漏洞;这将调用,在第169行,在可能的情况下在dsttmp
-一个临时文件上调用原子。因此,tl;博士:看起来@TomHale的答案不亚于GNUln-sf
!不幸的是(对我来说——令人惊讶的是),它看起来像FreeBSDln-sf
严格地比GNUln-sf
和目前公认的答案:at;在第342行替换文件之前,存在一个开放的争用条件;这与GNU和下面的Python答案形成对比,后者完全回避了这一点,代价是创建一个临时文件。选择你的毒药,我猜…(事实上,BSD使用它的事实让我重新考虑这是一个“坏”选项的既定结论)我为上面提到的安全漏洞提出了一个解决方案。你可以通过将mktemp
+symlink
调用放在一个循环中处理(不太可能的)比赛,重试直到你赢得比赛。显然,您需要检查symlink
是否因为EEXIST
而失败,而不是因为其他一些永远不会成功的原因。为了提高效率,您可能希望将嵌入的dirname
调用提升到循环上方。@ottomeister谢谢,您的建议会有所帮助。但是如何防止在创建后和替换符号链接之前更改名为mktemp
-的文件?您无法防止。任何对该目录具有写访问权限的行为不良的进程都可能破坏整个安排。重命名后,可能会有人替换或删除新的符号链接,就像重命名前可能会有人替换或删除一样。但是如果您担心并发的mktemp
s意外地碰撞到同一个名称,那么您可以mkdtemp
a目录,在该目录中创建新的符号链接,然后rename
将符号链接重命名为原始的符号链接(然后rmdir
temp目录)。文件系统中的重命名
是原子的。我有点惊讶于它没有出现在OOTB中。