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的答案不亚于GNU
    ln-sf
    !不幸的是(对我来说——令人惊讶的是),它看起来像FreeBSD
    ln-sf
    严格地比GNU
    ln-sf
    和目前公认的答案:at;在第342行替换文件之前,存在一个开放的争用条件;这与GNU和下面的Python答案形成对比,后者完全回避了这一点,代价是创建一个临时文件。选择你的毒药,我猜…(事实上,BSD使用它的事实让我重新考虑这是一个“坏”选项的既定结论)我为上面提到的安全漏洞提出了一个解决方案。你可以通过将
    mktemp
    +
    symlink
    调用放在一个循环中处理(不太可能的)比赛,重试直到你赢得比赛。显然,您需要检查
    symlink
    是否因为
    EEXIST
    而失败,而不是因为其他一些永远不会成功的原因。为了提高效率,您可能希望将嵌入的
    dirname
    调用提升到循环上方。@ottomeister谢谢,您的建议会有所帮助。但是如何防止在创建后和替换符号链接之前更改名为
    mktemp
    -的文件?您无法防止。任何对该目录具有写访问权限的行为不良的进程都可能破坏整个安排。重命名后,可能会有人替换或删除新的符号链接,就像重命名前可能会有人替换或删除一样。但是如果您担心并发的
    mktemp
    s意外地碰撞到同一个名称,那么您可以
    mkdtemp
    a目录,在该目录中创建新的符号链接,然后
    rename
    将符号链接重命名为原始的符号链接(然后
    rmdir
    temp目录)。文件系统中的
    重命名
    是原子的。我有点惊讶于它没有出现在OOTB中。