Wit*_*iko 4 ssh scp pipe btrfs
我打算将我的 btrfs 子卷的完整备份和增量备份传输到磁带存档服务。该服务公开 FTP 和 SSH 端点。如果允许我在 SSH 端点上执行任意命令,那么我将执行以下操作来执行增量备份:
btrfs send -p $LAST_SUBVOLUME $NEXT_SUBVOLUME | compress | encrypt |
ssh -p $PORT $USER@$ENDPOINT "cat > $SUBVOLUME.$YYYYMMDD.btrfs.bz2.gpg"
Run Code Online (Sandbox Code Playgroud)
但是,我不允许这样做:
$ ssh -p $PORT $USER@$ENDPOINT
Last login: Mon Jan 3 01:23:45 2067 from 123.456.789.123
This account is restricted by rssh.
Allowed commands: scp sftp rsync
If you believe this is in error, please contact your system administrator.
Connection to some.remote.endpoint closed.
Run Code Online (Sandbox Code Playgroud)
所以我想做的是使用 SCP 协议进行传输。但是,我的scp二进制文件拒绝传输命名管道:
$ scp -P $PORT <(btrfs send -p $LAST_SUBVOLUME $NEXT_SUBVOLUME | compress | encrypt) \
$USER@$ENDPOINT:$SUBVOLUME.$YYYYMMDD.btrfs.bz2.gpg
/dev/fd/63: not a regular file
Run Code Online (Sandbox Code Playgroud)
具有讽刺意味的是,显然, 编辑(2017-06-03):这是一个不正确的观察。正如 Kenster 所指出的,SCP 协议不允许发送大小未知的文件。scp曾经做过一次正确的事情。我想并不是每个人都认为传输命名管道是明智的/有用的。
更新 (2017-06-04):我也尝试使用 SFTP 协议传输数据。显然,FTP 协议允许发送未知大小的文件,正如对ftp ( link ) 和ncftpput ( link,部分描述,最后一段) 二进制文件中管道数据的支持所证明的那样。我发现,在SFTP客户我都试过(没有这样的支持sftp,lftp),这可能是一个迹象,SFTP(不像FTP)不支持未知大小(相反的将文件发送到我的想法,SFTP不仅仅是FTP tunelled通过SSH ; 这是一个不同的协议)。
更新 (2017-06-05):根据 SFTP 协议第 3 版 Internet 草案(链接),每个应用程序级数据包必须在有效载荷之前指定有效载荷长度(链接,第 3 节)。但是,SFTP 支持在写入的文件(链接,第 6.4 节)中查找,并明确支持超出当前文件末尾的写入。因此,如果应该可以在客户端使用一个小缓冲区并以已知大小的小块发送一个未知大小的文件:
btrfs send -p $LAST_SUBVOLUME $NEXT_SUBVOLUME | compress | encrypt |
ssh -p $PORT $USER@$ENDPOINT "cat > $SUBVOLUME.$YYYYMMDD.btrfs.bz2.gpg"
Run Code Online (Sandbox Code Playgroud)
但是,通过 shell 手动进行通信会非常痛苦。我正在寻找一个公开这种功能的 SFTP 客户端。
SCP 不太适合您的目的。SCP 协议不支持将未知大小的字节流发送到远程系统以保存为文件。发送文件的 SCP 协议消息要求先发送文件的大小,然后是组成文件的字节数。对于从管道读取的字节流,您通常不知道管道将产生多少字节,因此无法发送包含正确大小的 SCP 协议消息。
(我能找到的关于 SCP 协议的唯一在线描述是here和here。重点关注“C”消息的描述。)
SFTP 协议可用于此类事情。据我所知,普通的sftp命令行实用程序不支持读取管道并将其存储为远程文件。但是对于大多数现代编程语言(perl、python、ruby、C#、Java、C 等)都有 SSH/SFTP 库。如果您知道如何使用其中一种语言,那么编写一个满足您需要的实用程序应该很简单。
如果您坚持使用 shell 脚本,则可能会欺骗足够的 SCP 协议来传输文件。下面是一个例子:
#!/bin/bash
cmd='cat /etc/group'
size=$($cmd | wc -c)
{
echo C0644 $size some-file
$cmd
echo -n -e '\000'
} | ssh user@host scp -v -p -t /some/directory
Run Code Online (Sandbox Code Playgroud)
这将some-file在/some/directory具有权限 644 的远程系统上创建。文件内容将是$cmd写入其标准输出的任何内容。请注意,您正在运行该命令两次,其中包含暗示的任何资源消耗和副作用。并且该命令每次必须输出相同数量的字节。
lftp4.6.1 及更新版本应该能够执行此操作:https://github.com/lavv17/lftp/issues/104
不幸的是,链接问题中建议的命令不起作用,但稍加修改的命令可以:
lftp -p $port sftp://$user:$pass@$host -e "put /dev/stdin -o $filename"
Run Code Online (Sandbox Code Playgroud)
由于错误,如果您使用 SSH 代理,则必须在密码字段中提供某些内容。但任何随机字符串都可以。
该命令从 读取/dev/stdin。如果您必须使用不同的命名管道,我想这也应该可以工作 - 如果没有,您总是可以cat named-pipe | lftp ...。
我已经测试lftp了 >100GB 的上传,没有任何问题。
rclone还支持 SFTP,并且应该能够使用命令从管道输入上传rcat,该命令将于 1.38(下一版本)中发布。
| 归档时间: |
|
| 查看次数: |
1023 次 |
| 最近记录: |