14

通过 ssh 连接到远程主机时,我经常想将该系统上的文件带到本地系统以供查看或处理。有没有一种方法可以在不 (a) 打开新终端/暂停 ssh 会话 (b) 再次验证本地或远程主机的情况下复制文件 (c) 即使其中一个或两个主机都在后面NAT路由器?

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

4

11 回答 11

9

zssh(openssh 上的ZMODEM包装器)完全符合您的要求。

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

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

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

antti@local:~$ zssh remote
Press ^@ (C-Space) to enter file transfer mode, then ? for help
...
antti@remote:~$ sz zyxel.png
**B00000000000000
^@
zssh > rz
Receiving: zyxel.png
Bytes received:  104036/ 104036   BPS:16059729

Transfer complete
antti@remote:~$ 

上传过程类似,只是您只需切换rz(1)sz(1)

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

于 2008-09-08T15:45:44.060 回答
4

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

之后,
sshfs hostname:/ /PathToMountTo/
将在您的机器上挂载服务器文件系统,以便您可以访问它。

就我个人而言,我编写了一个小的 bash 脚本来添加我的密钥并挂载我最常使用的服务器,所以当我开始工作时,我只需要启动脚本并输入我的密码。

于 2008-09-08T15:37:06.140 回答
3

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

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

在下面的示例中,您应该只键入每个local>remote>ssh>提示符处的内容。

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/id_rsa.pub文件从本地机器传输到~/.ssh/authorized_keys远程机器的文件。

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 命令行,该命令行将为您提供以下命令:

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

在这个例子中,我LocalForward在 localhost 的 6666 端口上为客户端和服务器建立了一个端口;端口号可以是任意开放的端口。

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

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

接下来我们使用另一个转义字符~^Ztilde 后面跟着control-Z. 这会暂时挂起 ssh 进程并将我们放回 shell。

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

nc命令的其余部分是必需的,因为如果您还记得上面我说过该ssh进程被暂时挂起,因此&会将整个(sleep + nc)表达式置于后台,并sleep为您提供足够的时间让 ssh 以fg.

-R在第二个示例中,想法基本相同,只是我们使用而不是设置了一条通向另一个方向的隧道,-L以便我们建立一个RemoteForward. 然后在本地是您要使用-l参数的地方nc

默认情况下,转义字符是 ~ 但您可以使用以下方法更改它:

 -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 手册页中提供了对转义字符可用命令的完整说明

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).
于 2011-12-07T12:07:56.713 回答
1

使用 ControlMaster(-M 开关)是最好的解决方案,比这里的其他答案更简单、更容易。它允许您在多个会话之间共享单个连接。听起来像海报想要的那样。不过,您仍然必须键入 scp 或 sftp 命令行。尝试一下。我将它用于我所有的 sshing。

于 2011-05-30T08:10:03.577 回答
0

为了做到这一点,我将我的家庭路由器设置为将端口 22 转发回我的家庭机器(它有防火墙,只接受来自我的工作机器的 ssh 连接),我还设置了一个DynDNS帐户以提供动态 DNS将自动解析为我的家庭 IP。

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

#!/bin/bash

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

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

对于会话的其余部分,将文件发送回您的家庭计算机就像

scp file_to_send.txt your.domain.name:~/
于 2008-09-08T15:28:30.543 回答
0

这是一个名为 ssh-xfer 的 hack,它解决了确切的问题,但需要修补 OpenSSH,就我而言,这不是入门者。

于 2008-09-08T15:29:20.447 回答
0

这是我对这个问题的首选解决方案。在创建 ssh 会话时设置反向 ssh 隧道。这通过两个 bash 函数变得容易:grabfrom() 需要在本地主机上定义,而 grab() 应该在远程主机上定义。您可以添加您认为合适的任何其他 ssh 变量(例如 -X 或 -Y)。

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

用法:

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

正面:

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

负面:

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

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

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

于 2008-09-16T17:34:50.330 回答
0

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

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

于 2014-03-28T10:23:21.473 回答
0

使用它的最佳方法是通过 HTTP 公开文件并从另一台服务器下载它,您可以使用ZSSHPython 库实现此目的,

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

使用 PIP 安装它。

python3 -m pip install zssh

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

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

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

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

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

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

于 2020-04-25T21:21:08.980 回答
-1

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

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

我一直在 linksys 和 dlink 路由器后面这样做。我认为您可能需要更改一些设置,但这没什么大不了的。

于 2008-09-08T15:14:51.857 回答
-1

使用 -M 开关。

“将 ssh 客户端置于“主”模式以进行连接共享。多个 -M 选项将 ssh 置于“主”模式,在接受从连接之前需要确认。请参阅 ssh_config(5) 中对 ControlMaster 的描述细节。”

我不太明白这如何回答 OP 的问题 - 你能扩展一下吗,大卫?

于 2008-09-08T15:49:36.093 回答