我正在阅读一些通过 SSH 客户端发送文件的 Go 代码。
https://github.com/tmc/scp/blob/master/scp.go#L33
它所做的一件事是将scp -t /remote/path. 那-t旗子是干什么用的?我做了一个man scp,但似乎没有记录。我在本地运行了命令,它的行为似乎像 cat。
scp -t远程运行后,代码会像这样将字节发送到服务器。
// Some special control header? What is this?
fmt.Fprintf(w, "C%#o %d %s\n", mode, size, fileName)
// Send file bytes.
io.Copy(w, contents)
// Send termination signal?
fmt.Fprint(w, "\x00")
Run Code Online (Sandbox Code Playgroud)
这个协议是什么?它在任何地方都有记录吗?
AFAIK,scp 协议除了它的源代码之外没有记录在任何其他地方scp.c,因此这里尝试概述其scp工作原理。
当源或目标是远程机器时,scp将用于ssh连接并scp在其上启动程序:如果复制方向是从远程到本地,则以scp -f src(from / source)启动,否则为开始为scp -t dst(to / sink),本地scp将采取相反的姿势。
此后,两个 scp 进程在 scp 连接的两端运行,将其用作标准输入/标准输出并通过它传递文件数据和元数据。
两端都可以使用以下响应来确认消息或发出某些错误条件的信号:
"\0": 好的
"\1%s\n", err_msg: 非致命错误
"\2%s\n", err_msg: 致命错误
传输开始于to / sink scp发送\0(OK) ack。
然后from / source scp将使用以下消息:
"C%04o %lld %s\n", mode, size, filename: 创建文件
接下来size是文件数据字节和一个确认(\0= OK)
"D%04o 0 %.1024s\n", mode, dirname: 目录开始
递归后跟C,D或T消息,直到一个
"E\n": 目录结束
"T%llu 0 %llu 0\n", mtime, atime: 文件时间
如果使用了开关,这将在C或D消息之前发送-p。
这些消息在进一步处理之前必须由另一方确认,包括C发送文件数据之前,以及之后发送的确认。
在上面的C和D消息中,文件/目录名称中的换行符和其他控制字符(除了\t和\x7f)将被转义为例如。\^J,但不会在目的地被转义;文字\^J或\^M原始名称将保持原样。
致命错误和非致命错误的区别并不一致;只有\1(非致命的)差错将由任一侧产生,但它们中的一些将被认为是致命的,并且scp将退出时发送或接收它们,留下另一侧以保持两片。双方都会在\2(致命的)错误或任何意外情况下退出。
与 http 不同的是,没有规定按块发送文件数据;如果源scp不再能够读取它在C消息之后开始发送的一些大文件,它将size在\1错误消息/ nak之前发送最多NUL 字节。
| 归档时间: |
|
| 查看次数: |
738 次 |
| 最近记录: |