通过SSH会话将文件从远程主机带到本地主机的最佳方法是什么?

通过SSH会话将文件从远程主机带到本地主机的最佳方法是什么?

Which is the best way to bring a file from a remote host to local host over an SSH session?

通过ssh连接到远程主机时,我经常想将系统上的文件带到本地系统进行查看或处理。 有没有一种方法可以复制文件而无需(a)打开新终端/暂停ssh会话(b)再次向本地或远程主机进行身份验证,即使本地主机中的一个或两个都位于a后面,也可以正常工作(c) NAT路由器?

目标是尽可能多地利用当前状态:两台计算机之间存在连接,我在两台计算机上均已通过身份验证,并且我在文件的工作目录中-所以我 不必打开另一个终端并复制并粘贴远程主机和路径,这就是我现在要做的。 最好的解决方案也不需要在会话开始之前进行任何设置,但是如果设置是一次性的或能够自动化的,那将是完全可以接受的。


zssh(openssh上的ZMODEM包装器)完全可以满足您的需求。

  • 安装zssh并使用它而不是openssh(我假设您通常使用)

  • 您必须在两个系统上都安装了lrzsz软件包。

然后,要将文件zyxel.webp从远程主机传输到本地主机:

1
2
3
4
5
6
7
8
9
10
11
12
antti@local:~$ zssh remote
Press ^@ (C-Space) to enter file transfer mode, then ? for help
...
antti@remote:~$ sz zyxel.webp
**B00000000000000
^@
zssh > rz
Receiving: zyxel.webp
Bytes received:  104036/ 104036   BPS:16059729

Transfer complete
antti@remote:~$

上传的过程与此类似,只不过您只切换了rz(1)和sz(1)。

Putty用户可以尝试具有类似功能的Le Putty。


在Linux机器上,我使用ssh-agent和sshfs。您需要设置sshd以接受具有密钥对的连接。然后,您使用ssh-add将密钥添加到ssh-agent,这样就不必每次都键入密码。确保使用-t秒,这样密钥就不会永远保持加载状态。
ssh-add -t 3600 /home/user/.ssh/ssh_dsa

之后,
sshfs主机名:/ / PathToMountTo /
将服务器文件系统安装在您的计算机上,以便您可以访问它。

我个人编写了一个小的bash脚本,添加了我的密钥并挂载了我使用最多的服务器,因此,当我开始工作时,我只需要启动脚本并键入密码即可。


使用openssh的一些鲜为人知且很少使用的功能
实现您可以精确地完成您想要的!

  • 利用当前状态
  • 可以使用您所在的工作目录
  • 在会话开始之前不需要任何隧道设置
  • 不需要打开单独的端子或连接
  • 可以用作交互式会话中的一次性交易,也可以用作自动会话的一部分

您应该只键入local>remote>
ssh>在以下示例中提示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
local> ssh username@remote
remote> ~C
ssh> -L6666:localhost:6666
remote> nc -l 6666 < /etc/passwd
remote> ~^Z
[suspend ssh]
[1]+  Stopped                 ssh username@remote
local> (sleep 1; nc localhost 6666 > /tmp/file) & fg
[2] 17357
ssh username@remote
remote> exit
[2]-  Done                    ( sleep 1; nc localhost 6666 > /tmp/file )
local> cat /tmp/file
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
...

或者,更常见的是您想走另一个方向,例如,如果您
想要执行类似的操作,例如从
您的本地计算机到远程计算机的~/.ssh/authorized_keys文件
机。

1
2
3
4
5
6
7
8
9
10
11
12
13
local> ssh username@remote
remote> ~C
ssh> -R5555:localhost:5555
remote> ~^Z
[suspend ssh]
[1]+  Stopped                 ssh username@remote
local> nc -l 5555 < ~/.ssh/id_rsa.pub &
[2] 26607
local> fg
ssh username@remote
remote> nc localhost 5555 >> ~/.ssh/authorized_keys
remote> cat ~/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2ZQQQQBIwAAAQEAsgaVp8mnWVvpGKhfgwHTuOObyfYSe8iFvksH6BGWfMgy8poM2+5sTL6FHI7k0MXmfd7p4rzOL2R4q9yjG+Hl2PShjkjAVb32Ss5ZZ3BxHpk30+0HackAHVqPEJERvZvqC3W2s4aKU7ae4WaG1OqZHI1dGiJPJ1IgFF5bWbQl8CP9kZNAHg0NJZUCnJ73udZRYEWm5MEdTIz0+Q5tClzxvXtV4lZBo36Jo4vijKVEJ06MZu+e2WnCOqsfdayY7laiT0t/UsulLNJ1wT+Euejl+3Vft7N1/nWptJn3c4y83c4oHIrsLDTIiVvPjAj5JTkyH1EA2pIOxsKOjmg2Maz7Pw== username@local

需要一点解释。

第一步是打开LocalForward;如果您还没有
建立后,您可以使用~C转义符打开一个
ssh命令行,它将为您提供以下命令:

1
2
3
4
5
6
7
remote> ~C
ssh> help
Commands:
      -L[bind_address:]port:host:hostport    Request local forward
      -R[bind_address:]port:host:hostport    Request remote forward
      -D[bind_address:]port                  Request dynamic forward
      -KR[bind_address:]port                 Cancel remote forward

在此示例中,我在本地主机的端口6666上建立了LocalForward
对于客户端和服务器;端口号可以是任何
任意开放的端口。

nc命令来自netcat包;它被描述为
" TCP / IP瑞士军刀";这是一个简单但非常灵活的方法
有用的程序。使它成为UNIX工具带的标准部分。

此时,nc正在侦听端口6666并等待另一个
程序以连接到该端口,以便它可以发送
/etc/passwd

接下来,我们使用另一个转义字符~^Z,即tilde
control-Z。这会暂时中止ssh进程,并
让我们回到壳中

可以在本地系统上使用nc连接到
转发端口6666。请注意在这种情况下缺少-l,因为
选项告诉nc监听端口,就好像它是一台服务器一样。
不是我们想要的;相反,我们只想使用nc作为客户端
连接到远端已在监听的nc

需要使用nc命令其余的魔术,因为如果
您还记得上面我说过的ssh进程是暂时的
暂停,因此&会将整个(sleep + nc)表达式
进入背景,sleep为您提供了足够的时间让ssh
fg返回到前台。

在第二个示例中,除了我们设置
隧道使用-R而不是-l沿另一个方向移动,以便
我们建立一个RemoteForward。然后在本地方面
您要对nc使用-l参数。

默认情况下,转义字符是?,但是您可以使用以下命令更改该字符:

1
2
3
4
 -e escape_char
         Sets the escape character for sessions with a pty (default: ‘~’).  The escape character is only recognized at the beginning of a line.  The escape character followed by a dot
         (‘.’) closes the connection; followed by control-Z suspends the connection; and followed by itself sends the escape character once.  Setting the character to"none" disables any
         escapes and makes the session fully transparent.

ssh联机帮助页中提供了转义字符可用命令的完整说明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ESCAPE CHARACTERS
     When a pseudo-terminal has been requested, ssh supports a number of functions through the use of an escape character.

     A single tilde character can be sent as ~~ or by following the tilde by a character other than those described below.  The escape character must always follow a newline to be interpreted
     as special.  The escape character can be changed in configuration files using the EscapeChar configuration directive or on the command line by the -e option.

     The supported escapes (assuming the default ‘~’) are:

     ~.      Disconnect.

     ~^Z     Background ssh.

     ~#      List forwarded connections.

     ~&      Background ssh at logout when waiting for forwarded connection / X11 sessions to terminate.

     ~?      Display a list of escape characters.

     ~B      Send a BREAK to the remote system (only useful for SSH protocol version 2 and if the peer supports it).

     ~C      Open command line.  Currently this allows the addition of port forwardings using the -L, -R and -D options (see above).  It also allows the cancellation of existing remote port-
             forwardings using -KR[bind_address:]port.  !command allows the user to execute a local command if the PermitLocalCommand option is enabled in ssh_config(5).  Basic help is avail‐
             able, using the -h option.

     ~R      Request rekeying of the connection (only useful for SSH protocol version 2 and if the peer supports it).

使用ControlMaster(-M开关)是最好的解决方案,比此处的其余答案更简单。它允许您在多个会话之间共享一个连接。听起来像海报所要的那样。但是,您仍然必须键入scp或sftp命令行。试试吧。我将其用于所有的活动。


最好的使用方法是,您可以通过HTTP公开文件,然后从另一台服务器下载文件,可以使用ZSSH Python库实现此目的,

ZSSH-SSH上的ZIP(简单的Python脚本,用于在服务器之间交换文件)。

使用PIP安装它。

1
python3 -m pip install zssh

从远程服务器运行此命令。

1
python3 -m zssh -as --path /desktop/path_to_expose

它将为您提供一个URL,以从另一台服务器执行。

在需要下载这些文件并解压缩的本地系统或其他服务器中。

1
python3 -m zssh -ad --path /desktop/path_to_download --zip http://example.com/temp_file.zip

有关此库的更多信息:https://pypi.org/project/zssh/


您可以使用SCP协议传输文件。可以参考此链接

http://tekheez.biz/scp-protocol-in-unix/


这是我针对此问题的首选解决方案。创建ssh会话后,设置反向ssh隧道。通过两个bash函数可以轻松实现这一点:grabfrom()需要在本地主机上定义,而grab()应该在远程主机上定义。您可以根据需要添加其他所有使用的ssh变量(例如-X或-Y)。

1
2
function grabfrom() { ssh -R 2202:127.0.0.1:22 ${@}; };
function grab() { scp -P 2202 $@ localuser@127.0.0.1:~; };

用法:

1
2
3
4
localhost% grabfrom remoteuser@remotehost
password: <remote password goes here>
remotehost% grab somefile1 somefile2 *.txt
password: <local password goes here>

正面:

  • 它可以在OpenSSH以外的任何主机上都无需特殊软件即可工作
  • 当本地主机位于NAT路由器后面时,它可以工作
  • 它可以实现为一对两个单行bash函数

负面因素:

  • 它使用固定的端口号,因此:

    • 无法与远程主机建立多个连接
    • 可能与使用远程主机上的端口的进程冲突
  • 它需要localhost接受ssh连接
  • 在启动会话时需要特殊的命令
  • 它不会隐式处理对本地主机的身份验证
  • 它不允许在本地主机上指定目标目录
  • 如果您从多个本地主机抓取到同一远程主机,则ssh不会喜欢更改密钥

未来的工作:
这仍然是个难题。显然,可以通过适当地设置ssh密钥来处理身份验证问题,并且通过向grab()添加参数来允许指定远程目录更加容易。

解决其他负面问题更加困难。选择一个动态端口会很好,但是据我所知,没有一种优雅的方法可以将该端口传递给远程主机上的shell。尽我所知,OpenSSH不允许您在远程主机上设置任意环境变量,bash不能从命令行参数获取环境变量。即使您可以选择一个动态端口,也无法确保没有先连接就不会在远程主机上使用它。


这是一个名为ssh-xfer的黑客,它可以解决确切的问题,但需要修补OpenSSH,就我而言,这是一个入门。


为此,我将家庭路由器设置为将端口22转发回我的家庭计算机(该防火墙已防火墙保护,仅接受来自我的工作计算机的ssh连接),并且我还为DynDNS设置了一个帐户来提供动态DNS,会自动解析为我的家庭IP。

然后,当我SSH进入工作计算机时,我要做的第一件事就是运行一个脚本,该脚本启动ssh-agent(如果您的服务器没有自动执行此操作)。我运行的脚本是:

1
2
3
#!/bin/bash

ssh-agent sh -c 'ssh-add < /dev/null && bash'

它要求输入我的ssh密钥密码,这样我就不必每次都键入它。如果您使用不带密码的ssh密钥,则无需执行该步骤。

在剩余的会话中,将文件发送回您的家用计算机非常简单

1
scp file_to_send.txt your.domain.name:~/

使用-M开关。

"Places the ssh client into 'master' mode for connection shar-ing. Multiple -M options places ssh into ``master'' mode with confirmation required before slave connections are accepted. Refer to the description of ControlMaster in ssh_config(5) for details."

我不太清楚这如何回答OP的问题-David,您可以谈谈吗?


您应该能够设置公钥和私钥,以便不需要身份验证。

采取哪种方式取决于安全性要求等(请注意,有些linux / unix ssh蠕虫会查看密钥以查找可以攻击的其他主机)。

我一直在从linksys和dlink路由器后面进行此操作。我认为您可能需要更改几个设置,但这没什么大不了的。


推荐阅读

    改文件linux命令行?

    改文件linux命令行?,地址,系统,工作,信息,数字,文件,命令,设备,密码,权限,lin

    linux查u盘系统命令?

    linux查u盘系统命令?,系统,设备,电脑,信息,管理,定期,软件,密码,生产,百分比

    linux系统关键命令?

    linux系统关键命令?,地址,工作,系统,信息,命令,目录,检测,环境,工具,设备,Lin

    拷贝文件夹linux命令?

    拷贝文件夹linux命令?,系统,地址,服务,信息,密码,情况,单位,项目,命令,文件,l

    打包文件命令linux?

    打包文件命令linux?,系统,时间,工具,名称,命令,文件,目录,格式,表示,详细信

    linux系统命令终端?

    linux系统命令终端?,系统,首页,终端,设备,电脑,情况,信息,命令,界面,用户,lin

    linux中文件编辑命令?

    linux中文件编辑命令?,系统,工作,工具,信息,地址,发行,命令,第一,检测,基础,l

    linux创建主机名命令?

    linux创建主机名命令?,工作,地址,系统,信息,名称,命令,目录,发行,查询系统,

    linux文件格式的命令?

    linux文件格式的命令?,设备,命令,系统,文件,标准,代码,情况,电脑,平台,数据,l

    linux系统vi命令?

    linux系统vi命令?,档案,状态,系统,命令,正规,数字,模式,编辑,文件,光标,linux

    linux命令行编译文件?

    linux命令行编译文件?,代码,系统,项目,工具,网上,手机,电脑,地址,官网,文件,L

    linux下文件写入命令?

    linux下文件写入命令?,系统,信息,文件,名字,电脑,软件,目录,命令,内容,指令,l

    linux命令备份文件夹?

    linux命令备份文件夹?,设备,系统,文件,命令,备份,情况,做好,名字,灵活,数据,l

    linux系统命令调用?

    linux系统命令调用?,系统,单位,工具,工作,管理,地址,权威,密码,电脑,信息,怎

    linux麒麟系统命令行?

    linux麒麟系统命令行?,系统,银河,电脑,设备,公司,信息,手机,密码,平台,麒麟,

    linux系统man命令?

    linux系统man命令?,信息,地址,系统,工作,命令,数据,管理,单位,目录,文件,linu

    虚拟机linux系统命令?

    虚拟机linux系统命令?,系统,工具,软件,名字,时间,命令,工作,首次,环境,名称,L

    linux系统查端口命令?

    linux系统查端口命令?,系统,状态,地址,检测,工具,网络,信息,灵活,服务,端口,l

    linux命令deb文件?

    linux命令deb文件?,软件,位置,第一,系统,中心,工具,信息,发行,网站,管理系统

    linux系统分屏命令?

    linux系统分屏命令?,系统,工具,地址,工作,命令,基础知识,信息,时间,情况,技