为了账号安全,请及时绑定邮箱和手机立即绑定

如何覆盖 Go 中的符号链接?

如何覆盖 Go 中的符号链接?

Go
慕莱坞森 2022-01-10 17:32:24
我想用 Go 覆盖一个符号链接,但我找不到怎么做。如果我尝试创建符号链接并且它已经存在,则会返回错误。我的代码:err := os.Symlink(filePath, symlinkPath)if err != nil {    fmt.Println(err)}我猜必须删除符号链接,然后重新创建。是对的吗?如果是这样,我该如何取消链接符号链接?
查看完整描述

3 回答

?
宝慕林4294392

TA贡献2021条经验 获得超8个赞

只需检查符号链接是否存在并在创建新链接之前将其删除


if _, err := os.Lstat(symlinkPath); err == nil {

  os.Remove(symlinkPath)

}


查看完整回答
反对 回复 2022-01-10
?
BIG阳

TA贡献1859条经验 获得超6个赞

这里的其他答案是正确的......但有两个小问题:

  • 有一个微小的数据竞争,新的符号链接将在此处之前但在删除之后的其他地方创建,使其处于潜在的不一致状态。

  • 如果程序在创建符号链接之前死亡/崩溃,但在删除前一个符号链接之后,它可能会再次使事情处于不一致的状态。

处理这个问题的更原子的方法是创建一个临时符号链接,然后将其重命名为原始符号链接:

symlinkPathTmp := symlinkPath + ".tmp"

if err := os.Remove(symlinkPathTmp); err != nil && !os.IsNotExist(err) {

  return err

}


if err := os.Symlink(filePath, symlinkPathTmp); err != nil {

  return err

}


if err := os.Rename(symlinkPathTmp, symlinkPath); err != nil {

  return err

}

在删除临时链接和重新创建它之间仍然存在小竞争,但它不会冒使主要链接处于不一致状态的风险。理想情况下,我们可以通过为临时链接使用随机名称来解决这个问题,但是 Go 的 TempFile 总是会创建一个新文件,因此它不是很有用。(您可以调用 TempFile,然后删除文件名并重新使用该名称,这会比仅附加一个常量.tmp后缀更危险但更安全。)


然而,即使有那场比赛,你仍然可以获得原子性,任何中断都不会导致丢失链接。


请注意,这取决于 Posix 行为,并且可能无法在 Windows 上运行(为什么还要在 Windows 上使用符号链接?),但它是许多需要原子符号链接替换的 macOS/Linux 工具共享的技术。


查看完整回答
反对 回复 2022-01-10
?
MYYA

TA贡献1868条经验 获得超4个赞

请注意,@Vadyus 的答案在运行 lstat 时隐藏了实际的文件系统错误。例如,如果您的磁盘损坏并且 Lstat 失败,您仍然会运行 os.Remove 并忽略它的错误(危险,除非您喜欢调试几个小时)。


以下片段正确检查文件是否存在和其他错误:


if _, err := os.Lstat(symlinkPath); err == nil {

  if err := os.Remove(symlinkPath); err != nil {

      return fmt.Errorf("failed to unlink: %+v", err)

  }

} else if os.IsNotExist(err) {

    return fmt.Errorf("failed to check symlink: %+v", err)

}


查看完整回答
反对 回复 2022-01-10
  • 3 回答
  • 0 关注
  • 155 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信