在代码中通过 SSH 发送文件的协议是什么?

425*_*esp 6 linux ssh scp

我正在阅读一些通过 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)

这个协议是什么?它在任何地方都有记录吗?

mos*_*svy 7

AFAIK,scp 协议除了它的源代码之外没有记录在任何其他地方scp.c,因此这里尝试概述其scp工作原理。

当源或目标是远程机器时,scp将用于ssh连接并scp在其上启动程序:如果复制方向是从远程到本地,则以scp -f srcfrom / source)启动,否则为开始为scp -t dstto / sink),本地scp将采取相反的姿势。

此后,两个 scp 进程在 scp 连接的两端运行,将其用作标准输入/标准输出并通过它传递文件数据和元数据。

两端都可以使用以下响应来确认消息或发出某些错误条件的信号:

  1. "\0": 好的

  2. "\1%s\n", err_msg: 非致命错误

  3. "\2%s\n", err_msg: 致命错误

传输开始于to / sink scp发送\0(OK) ack。

然后from / source scp将使用以下消息:

  1. "C%04o %lld %s\n", mode, size, filename: 创建文件

    接下来size是文件数据字节和一个确认(\0= OK)

  2. "D%04o 0 %.1024s\n", mode, dirname: 目录开始

    递归后跟C,DT消息,直到一个

  3. "E\n": 目录结束

  4. "T%llu 0 %llu 0\n", mtime, atime: 文件时间

    如果使用了开关,这将在CD消息之前发送-p

这些消息在进一步处理之前必须由另一方确认,包括C发送文件数据之前,以及之后发送的确认。

在上面的CD消息中,文件/目录名称中的换行符和其他控制字符(除了\t\x7f)将被转义为例如。\^J,但不会在目的地被转义;文字\^J\^M原始名称将保持原样。

致命错误和非致命错误的区别并不一致;只有\1(非致命的)差错将由任一侧产生,但它们中的一些将被认为是致命的,并且scp将退出时发送或接收它们,留下另一侧以保持两片。双方都会在\2(致命的)错误或任何意外情况下退出。

与 http 不同的是,没有规定按块发送文件数据;如果源scp不再能够读取它在C消息之后开始发送的一些大文件,它将size\1错误消息/ nak之前发送最多NUL 字节。