发送者和接收者根据请求通过ssh传输文件?

时间:2009-02-05 12:35:07

标签: unix shell ssh sysadmin file-transfer

我创建了一个程序,它遍历一堆文件并调用其中一些文件:

scp <file> user@host:<remotefile>

但是,在我的情况下,可能有数千个小文件需要传输,而scp正在为每个文件打开一个新的ssh连接,这有很大的开销。

我想知道是否有一个解决方案,我保持一个进程保持连接的运行,我可以发送“请求”来复制单个文件。

理想情况下,我正在寻找一些发送器和接收器程序的组合,这样我就可以在开始时启动一个进程(1):

ssh user@host receiverprogram

对于每个文件,我调用一个命令(2):

senderprogram <file> <remotefile>

并将(2)的输出传递给(1)的输入,这将导致文件被传输。最后,我可以向进程(1)发送一些信号来终止。

发送方和接收方程序最好是Unix的开源C程序。他们可以使用套接字而不是管道或任何其他创造性解决方案进行通信。

然而,在我迭代它时,每个文件都被传输是一个重要约束:收集文件列表然后调用{{1}的一个实例是不可接受的最后一次传输所有文件。此外,我只有简单的shell访问接收主机。

更新:我找到了使用ssh的多路复用功能解决连接开销问题的解决方案,请参阅下面的答案。然而,我正在开始赏金,因为我很想知道是否存在我在这里描述的发送者/接收者程序。似乎应该存在可以使用的东西,例如XMODEM / YMODEM / ZMODEM?

14 个答案:

答案 0 :(得分:23)

我从另一个角度找到了解决方案。自version 3.9起,OpenSSH支持会话多路复用:单个连接可以承载多个登录或文件传输会话。这可以避免每个连接的设置成本。

对于问题的情况,我可以首先打开一个连接,在特定位置设置一个带有套接字(-M)的控制主控(-S)。我不需要会话(-N)。

ssh user@host -M -S /tmp/%r@%h:%p -N

接下来,我可以为每个文件调用scp并指示它使用相同的套接字:

scp -o 'ControlPath /tmp/%r@%h:%p' <file> user@host:<remotefile>

此命令几乎立即开始复制!

您也可以使用控制套接字进行正常的ssh连接,然后立即打开:

ssh user@host -S /tmp/%r@%h:%p

如果控制套接字不再可用(例如,因为您杀死了主控制器),则会回退到正常连接。有关详细信息,请参阅this article

答案 1 :(得分:4)

使用sftp而不是scp可能会有效,并将其置于批处理模式。使批处理命令文件成为管道或UNIX域套接字,并根据需要将命令提供给它。

在客户端安全性可能有点棘手。

答案 2 :(得分:4)

你试过sshfs吗? 你可以:

sshfs remote_user@remote_host:/remote_dir /mnt/local_dir

哪里

  • /remote_dir是您要将文件发送到正在进入的系统的目录
  • /mnt/local_dir是本地装载位置

通过此设置,您可以cplocal_dir文件放入sftp,并通过remote_hostremote_dir发送至-o ServerAliveInterval=15

请注意,只有一个连接,因此几乎没有开销

您可能需要使用标记sftp来维护indefinite connection

您需要在本地安装fuse,并支持(并配置){{1}}

的SSH服务器

答案 3 :(得分:4)

这种方式可行,而对于其他方面,这种一般方法或多或少是正确的。

(
iterate over file list
  for each matching file
   echo filename
) | cpio -H newc -o | ssh remotehost cd location \&\& | cpio -H newc -imud

答案 4 :(得分:3)

可能你正在寻找这个: ZSSH

  

zssh(Zmodem SSH)是一个在使用安全shell(ssh)时以交互方式将文件传输到远程计算机的程序。它旨在成为scp的一种方便的替代方案,允许传输文件而无需打开另一个会话并重新验证自己。

答案 5 :(得分:2)

如果可以收集要在单个目录(或目录层次结构)中发送的所有文件,请在ssh上使用rsync。

如果您没有将所有文件放在一个位置,请提供一些有关您想要实现的内容的更多信息,以及为什么您无法将所有文件打包到存档中并将其发送过来。为什么每个文件立即发送至关重要?如果文件是在短时间内发送的(比如积累了4K值的数据),那会没关系吗?

答案 6 :(得分:2)

这是个小问题。我不知道预先打包的解决方案,但您可以使用简单的shell脚本做很多事情。我会在接收器上尝试这个:

#!/bin/ksh
# this is receiverprogram

while true
do
  typeset -i length
  read filename  # read filename sent by sender below
  read size      # read size of file sent
  read -N $size contents  # read all the bytes of the file
  print -n "$contents" > "$filename"
done

在发送方,我会创建一个命名管道并从管道读取,例如,

mkfifo $HOME/my-connection
ssh remotehost receiver-script < $HOME/my-connection

然后发送文件我会尝试这个脚本

#!/bin/ksh
# this is senderprogram

FIFO=$HOME/my-connection

localname="$1"
remotename="$2"
print "$remotename" > $FIFO
size=$(stat -c %s "$localname")
print "$size" > $FIFO
cat "$localname" > $FIFO

如果文件大小很大,您可能不想一次性阅读,所以

的顺序
BUFSIZ=8192

rm -f "$filename"
while ((size >= BUFSIZ)); do
  read -N $BUFSIZE buffer
  print -n "$buffer" >> "$filename"
  size=$((size - BUFSIZ))
done
read -N $size buffer
print -n "$contents" >> "$filename"

最终,您需要扩展脚本,以便可以通过chmodchgrp命令。由于您信任发送代码,因此最简单的结构是接收器只需在每一行上调用shell eval,然后发送类似

的内容
print filename='"'"$remotename"'"' > $FIFO
print "read_and_copy_bytes " '$filename' "$size" > $FIFO

然后定义本地函数read_and_copy_bytes。获得正确的报价是一只熊,否则它应该是直截了当的。

当然,这些都没有经过测试!但我希望它能给你一些有用的想法。

答案 7 :(得分:1)

看起来像焦油的工作?将其输出传递给ssh,另一方面将ssh输出传递回tar。

答案 8 :(得分:1)

我认为GNOME桌面在通过SFTP(SSH)访问共享时使用单个SSH连接。我猜这是正在发生的事情,因为当我以这种方式访问​​远程共享时,我看到一个SSH进程。因此,如果这是真的,您应该能够为此目的使用相同的程序。

新版本的GNOME通过GIO使用GVFS,以便通过不同的后端执行所有类型的I / O. Ubuntu包gvfs-bin提供了各种命令行实用程序,可以让您从命令行操作后端。

首先,您需要安装SSH文件夹:

gvfs-mount sftp:// user @ host /

然后您可以使用gvfs-copy复制文件。我认为所有文件传输都将通过一个SSH进程执行。您甚至可以使用ps来查看正在使用的进程。

如果您觉得更有冒险精神,您甚至可以用C或其他一些为GIO提供API的高级语言编写自己的程序。

答案 9 :(得分:1)

一个选项是Conch是使用Twsited框架用Python编写的SSH客户端和服务器实现。您可以使用它编写一个工具,通过其他协议(HTTP或Unix域套接字,FTP,SSH或其他)接受请求,并通过长时间运行的SSH连接触发文件传输。事实上,我有几个生产程序使用这种技术来避免多个SSH连接设置。

答案 10 :(得分:1)

几周之前有a very similar question hereaccepted answer建议在ssh到远程计算机时打开隧道并使用该隧道进行scp传输。

答案 11 :(得分:1)

Perhapse CurlFTPFS可能是您的有效解决方案。

看起来它只是通过SFTP将外部计算机的文件夹安装到您的计算机上。完成后,您应该可以使用常规cp命令,一切都将安全完成。

不幸的是我自己无法测试它,但请告诉我它是否适用于你!

编辑1:我已经能够下载并测试它了。因为我担心它确实要求客户端有FTP服务器。 然而,我发现另一个程序与您正在寻找的概念完全相同。 sshfs允许您连接到客户端计算机而无需任何特殊服务器。一旦安装了其中一个文件夹,就可以使用普通的cp命令将所需的任何文件移动到更多文件中。完成后,它应该是umount /path/to/mounted/folder的微笑问题。让我知道这是如何工作的!

答案 12 :(得分:0)

rsync -avlzp user@remotemachine:/path/to/files /path/to/this/folder

这将使用SSH以非慢速方式传输文件

答案 13 :(得分:0)

保持简单,写一个像这样做的小包装脚本。

  1. tar文件
  2. 发送tar文件
  3. 在另一边解开
  4. 这样的事情:

    1. tar -cvzf test.tgz files ....
    2. scp test.tgz user@other.site.com:。
    3. ssh user@other.site.com tar -xzvf test.tgz
    4. /约翰