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

我想用 Go 覆盖一个符号链接,但我找不到怎么做。


如果我尝试创建符号链接并且它已经存在,则会返回错误。


我的代码:


err := os.Symlink(filePath, symlinkPath)

if err != nil {

    fmt.Println(err)

}

我猜必须删除符号链接,然后重新创建。是对的吗?如果是这样,我该如何取消链接符号链接?


慕莱坞森
浏览 156回答 3
3回答

宝慕林4294392

只需检查符号链接是否存在并在创建新链接之前将其删除if _, err := os.Lstat(symlinkPath); err == nil {  os.Remove(symlinkPath)}

BIG阳

这里的其他答案是正确的......但有两个小问题:有一个微小的数据竞争,新的符号链接将在此处之前但在删除之后的其他地方创建,使其处于潜在的不一致状态。如果程序在创建符号链接之前死亡/崩溃,但在删除前一个符号链接之后,它可能会再次使事情处于不一致的状态。处理这个问题的更原子的方法是创建一个临时符号链接,然后将其重命名为原始符号链接: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 工具共享的技术。

MYYA

请注意,@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)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go