你正在使用哪个版本的Go( go version
)?
$ go version
go version go1.15.2 darwin/amd64
这个问题在最新版本中是否会重现?
是的
你正在使用什么操作系统和处理器架构( go env
)?
go env
输出
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/danny/Library/Caches/go-build"
GOENV="/Users/danny/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/danny/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/danny/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/Cellar/go/1.15.2/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.15.2/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/danny/workspace/media-sort/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/36/kj75t85j1m57cg047cr5dh4m0000gn/T/go-build628346493=/tmp/go-build -gno-record-gcc-switches -fno-common"
你做了什么?
我在Mac上进行交叉编译以便为Linux系统编译
Linux执行环境: Linux nas 4.4.190.x86_64.1 #1 SMP Mon Oct 28 01:55:46 UTC 2019 x86_64 GNU/Linux
构建命令: GOOS=linux GOARCH=amd64 go build -v
func move(src, dst string) error {
err := os.Rename(src, dst)
// cross device move
if err != nil && strings.Contains(err.Error(), "cross-device") {
if err := copy(src, dst); err != nil {
return err
}
if err := os.Remove(src); err != nil {
return err
}
}
return nil
}
你期望看到什么?
os.Rename()
能够成功,因为源文件和目标文件位于同一个文件系统上。
你实际上看到了什么?
os.Rename()
返回 "invalid cross-device link",上述代码回退到复制并删除。如果我在命令行上执行一个 mv
,它会立即完成 - 即使对于多GB的文件也是如此。
6条答案
按热度按时间2w2cym1i1#
os.Rename
是一个相当薄的syscall.Rename
Package 器,它只是调用rename
系统调用。如果可能的话,请在strace -f
下运行最终的 GNU/Linux 可执行文件,并查看rename
系统调用返回的结果。zazmityj2#
感谢您的快速回复 @ianlancetaylor 。为了测试,我在我的 NAS 上的
/data/Videos
中创建了一个空文件f
,并将mv
-ed 到/data/Music
。这里是strace
的内容:我在这里远远不够深入,但我猜测这些行是重要的:
看起来
rename
调用失败了,而mv
回退到使用 BTRFS 特定的替代方案。fkaflof63#
有趣的。我之前不知道这个。我会重新命名这个问题。
lfapxunr4#
我尝试跟踪
mv
的来源,但是...嗯...我不是C程序员!🤣但最终,它在这里结束:https://github.com/coreutils/coreutils/blob/master/src/copy.c#L405-L418,据我所知,它来自这里:https://github.com/coreutils/coreutils/blob/master/src/copy.c#L1459。最终,似乎都由
mv.c
中以下两个标志的默认值控制:https://github.com/coreutils/coreutils/blob/master/src/mv.c#L113
https://github.com/coreutils/coreutils/blob/master/src/mv.c#L130
lokaqttq5#
有趣的是,BTRFS报告这两个目录位于不同的文件系统,但然后却乐于进行CoW操作!
zdwk9cvp6#
可能相关的: https://superuser.com/questions/948808/why-is-moving-files-between-btrfs-subvolumes-an-expensive-operation