【发布时间】:2020-11-11 14:38:42
【问题描述】:
我正在尝试在 Go 中编写一个简单的 FTP 客户端,它将连接到 FTP 服务器,下载与特定模式 (*.xml) 匹配的任何文件,然后将它们从服务器中删除。我使用 Go 是因为它易于使用支持交叉编译(对开发很重要)并生成单个静态二进制文件(对部署很重要)。 Linux 二进制文件在 Ubuntu 20.04(用于开发的主机平台)和我的 Windows 10 Home 笔记本电脑(交叉编译:GOARCH=windows go build ftp-test.go)上运行良好。但是,在 Windows 10 Pro 机器上,我得到了一个似乎与 DNS 解析有关的异常和堆栈跟踪(下面的完整输出)。
最简单的客户端版本如下:
package main;
import (
"fmt"
"time"
"github.com/jlaffaye/ftp"
)
func main() {
fmt.Println("Connecting to FTP server")
_, err := ftp.Dial("ftp.mirrorservice.org:21", ftp.DialWithTimeout(60*time.Second))
if err != nil {
fmt.Println(err)
}
}
完整的客户端源代码较长,但是当调用ftp.Dial 时会发生异常,以上是触发它所需的最少代码。异常几乎立即发生,远在 60 秒超时之前。
完整的堆栈跟踪是:
.\ftp-test.exe
Connecting to FTP server
Exception 0xc0000005 0x0 0x7ffae1952fff 0x28cb44e0000
PC=0x28cb44e0000
syscall.Syscall6(0x7ffae07f4c70, 0x4, 0xc0000b60c0, 0x0, 0xc000037f18, 0xc000037e88, 0x0, 0x0, 0x0, 0x0, ...)
/snap/go/6715/src/runtime/syscall_windows.go:201 +0xf2
syscall.GetAddrInfoW(0xc0000b60c0, 0x0, 0xc000037f18, 0xc000037e88, 0x16, 0x0)
/snap/go/6715/src/syscall/zsyscall_windows.go:1718 +0xe5
net.(*Resolver).lookupIP.func1(0x0, 0x0, 0x0, 0x0, 0x0)
/snap/go/6715/src/net/lookup_windows.go:109 +0x259
net.(*Resolver).lookupIP.func2(0xc0000985c0, 0xc0000e8120)
/snap/go/6715/src/net/lookup_windows.go:146 +0x32
created by net.(*Resolver).lookupIP
/snap/go/6715/src/net/lookup_windows.go:145 +0x41b
goroutine 1 [select]:
net.(*Resolver).lookupIPAddr(0x5268e0, 0x41e1e0, 0xc0000e8000, 0x3dbef9, 0x3, 0x3e146f, 0x15, 0x15, 0x0, 0x0, ...)
/snap/go/6715/src/net/lookup.go:299 +0x685
net.(*Resolver).internetAddrList(0x5268e0, 0x41e1e0, 0xc0000e8000, 0x3dbef9, 0x3, 0x3e146f, 0x18, 0x0, 0x0, 0x0, ...)
/snap/go/6715/src/net/ipsock.go:280 +0x4d4
net.(*Resolver).resolveAddrList(0x5268e0, 0x41e1e0, 0xc0000e8000, 0x3dc010, 0x4, 0x3dbef9, 0x3, 0x3e146f, 0x18, 0x0, ...)
/snap/go/6715/src/net/dial.go:221 +0x49d
net.(*Dialer).DialContext(0xc0000e6010, 0x41e1a0, 0xc0000a2058, 0x3dbef9, 0x3, 0x3e146f, 0x18, 0x0, 0x0, 0x0, ...)
/snap/go/6715/src/net/dial.go:403 +0x23c
github.com/jlaffaye/ftp.Dial(0x3e146f, 0x18, 0xc0000cbf50, 0x1, 0x1, 0x19, 0x0, 0x0)
/home/paul/go/src/github.com/jlaffaye/ftp/ftp.go:105 +0x5fc
main.main()
/home/paul/ftp-test.go:11 +0xe5
goroutine 19 [select]:
net.(*Resolver).lookupIP(0x5268e0, 0x41e160, 0xc0000ea000, 0x3dbef9, 0x3, 0x3e146f, 0x15, 0x0, 0x0, 0x0, ...)
/snap/go/6715/src/net/lookup_windows.go:151 +0x1b9
net.glob..func1(0x41e160, 0xc0000ea000, 0xc0000886c0, 0x3dbef9, 0x3, 0x3e146f, 0x15, 0x0, 0x0, 0x0, ...)
/snap/go/6715/src/net/hook.go:23 +0x79
net.(*Resolver).lookupIPAddr.func1(0x0, 0x0, 0x0, 0x0)
/snap/go/6715/src/net/lookup.go:293 +0xc2
internal/singleflight.(*Group).doCall(0x5268f0, 0xc0000d60a0, 0xc0000a0760, 0x19, 0xc0000ea040)
/snap/go/6715/src/internal/singleflight/singleflight.go:95 +0x35
created by internal/singleflight.(*Group).DoChan
/snap/go/6715/src/internal/singleflight/singleflight.go:88 +0x2cc
rax 0x7ffaddecd84a
rbx 0x7ffaddecd848
rcx 0x77
rdi 0xffffffffffbadd11
rsi 0x0
rbp 0x28cb45135d0
rsp 0xbc5e7fe300
r8 0x94b
r9 0x94b
r10 0x94b
r11 0x94b
r12 0x7ffae1760000
r13 0x0
r14 0x7ffaddecd84a
r15 0xc000007a
rip 0x28cb44e0000
rflags 0x10202
cs 0x33
fs 0x53
gs 0x2b
我已经试过了:
- 使用
go get -v -u all更新所有依赖项。 - 通过删除二进制文件强制重新编译代码(我通常使用 Makefile 仅在必要时重新编译)。
- 手动运行 DNS 查找,例如
nslookup ftp.mirrorservice.org- 这将返回我期望的 IP 地址。 - 在命令行上使用
ftp连接到 FTP 服务器 - 可以。 - 尝试一个简单的“hello world”二进制文件 - 这行得通(例如,如果我删除
fmt.Println("Connecting to FTP server")行之外的所有内容,二进制文件运行没有任何问题)。 - 当 Windows 防火墙配置为阻止所有出站连接时,在 Windows 10 Home 上运行二进制文件。这会导致一条错误消息(不是堆栈跟踪异常),指出二进制文件正在尝试访问套接字并且这是被禁止的。
- 在 Windows 10 Home 上编译源代码,即不使用 Linux 的交叉编译。该二进制文件在 Ubuntu(使用 WINE)和 Windows 10 Home 上运行,但在 Windows 10 Pro 机器上失败并出现同样的错误。
很遗憾,我对 Windows 10 Pro 机器的访问权限有限,因此无法安装 Go 工具链(例如)。
我是 Go 的新手,很少将 Windows 作为平台,所以我不确定问题是否与我的代码、我用于 FTP 的第三方库或 Windows(或组合)有关。
我的 Go 版本是:1.15.4 linux/amd64 和 1.14.7 windows/amd64
【问题讨论】:
-
这可能是由于某些外部软件试图阻止 Go 进行所需的系统调用。如果在 windows 上搜索这个错误,几乎所有结果都指向 WebCompanion 或其他 LavaSoft 产品。