如何在已经通过 ssh 连接到服务器的情况下通过 ssh 传输文件

如何在已经通过 ssh 连接到服务器的情况下通过 ssh 传输文件

我使用此命令传输文件

scp <localfile> user@host:<destination>

仅当我未通过 ssh 进入服务器时,上述命令才有效。

当我已经通过 ssh 登录时,如何将本地文件传输到主机?

我正在使用 sshssh user@hostname

答案1

好问题。scp再次,但方法相反。我这样做了,结果如下:

chris@local ~$ ls hos*
hosts
chris@local ~$ ssh remote
Last login: Fri Mar  8 15:52:25 2013 from local
chris@remote ~$ scp chris@local:hos* .
chris@local's password: 
hosts                                              100% 1850     1.8KB/s   00:00    
chris@remote ~$ ls hos*
hosts
chris@remote ~$ 

编辑并添加:正如评论中指出的那样,这需要远程计算机能够访问本地计算机。并且需要在本地计算机上安装并运行 sshd 或 (openssh-server)。

答案2

在我看来,所有这些“scp”答案都没有回答这个问题。

最简单的方法

你可以使用 ssh 进行标准 I/O 重定向,如下所示

$ ssh user@host "dd if=path-of-file" | dd of=where-to-copy

bs您可以在此处使用多种方式控制流量甚至进行压缩:

$ ssh -C user@host "dd if=path-of-file" | dd of=where-to-copy

或者类似的东西:

$ ssh user@host "lzma -c path-of-file" | lzma -d - > where-to-copy

其他方式!

对于第二种方法,我们假设你没有 root 权限,由于某种原因第一种方法不起作用,你无法在远程主机上真正安装东西。你将大概有内置 web 服务器的 python。所以这里有个窍门。

test.txt假设你正在尝试获取目录中的文件/tmp/test

$ ssh -o EnableEscapeCommandline=yes user@hostname
host$ cd /tmp/test
host$ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 ...

现在通常我们无法访问它,因为它已绑定到本地主机。

因此,我们将使用转义序列进入 SSH 命令 shell

~C

接下来,我们将对远程机器进行 SOCKS 转发。选择一个更高级别的端口,例如 4321

ssh> -D 0.0.0.0:4321
Forwarding port.

好的,让它继续运行。终端 2 时间到了!我们将使用端口 4321 作为 SOCKS 代理,这将带我们到达远程计算机。从那里,我们将访问“localhost”,它将是远程计算机的 localhost。curl 可以轻松将其提供给我们。

$ curl --preproxy SOCKS://localhost:4321 http://localhost:8000/test.txt

还有第三个

你回头对我说:“我甚至没有 Python!”你有 Bash 吗?你可能有 Bash。让我们这样做吧。

在您的本地主机上,我们将使用 netcat。让我们选择一个端口,例如 5445。因此终端 1

$ nc -lp 5445 > where-to-put-it

终端 2 我们将使用反向端口转发来访问 ssh。此外,我们只需省去一些输入,并使用 0 作为 的折叠0.0.0.0

$ ssh -R 0:5000:0:5445 user@host 'bash -c "cat path-of-file > /dev/tcp/0/5000"'   

还有第四个!

好吧,假设您没有 scp,没有 bash,没有 python,管道解决方案不起作用,GatewayPorts 被禁用,天哪,您现在真的陷入困境了,对吧?

废话!base64 来救场了!它包含在 busybox 中,您几乎可以在所有东西上找到它。开始吧!

首先,我们建立所谓的“障碍条件”。我们将使用 UUID

$ uuidgen
14184b38-5fec-41ba-a94e-0de94d5a417a

现在我们要登录并将整个会话发送到一个文件

$ ssh user@remote | tee /tmp/session
host> echo 14184b38-5fec-41ba-a94e-0de94d5a417a;base64 somefile;echo 14184b38-5fec-41ba-a94e-0de94d5a417a

等待它闪过您的会话并注销。

现在我们将使用屏障条件和换行符来提取有效载荷

$ cat /tmp/session |\
  sed -zE -s/'(^.*?14184b38-5fec-41ba-a94e-0de94d5a417a\r\n)(.*?)(\r\n4184b38-5fec-41ba-a94e-0de94d5a417a.*)/\2/g'

现在应该只剩下文件的 base64 编码了。我们快完成了,只需要删除换行符

$ cat /tmp/session |\
  sed -zE -s/'(^.*?14184b38-5fec-41ba-a94e-0de94d5a417a\r\n)(.*?)(\r\n4184b38-5fec-41ba-a94e-0de94d5a417a.*)/\2/g' |\
  tr -d '\r\n' |\
  base64 -d > where-to-put-it

自主学习

使用最后一个,你可以做一些非常有趣的事情,我会把它作为练习留给读者。

  1. 不要重定向到文件,而是使用fifo管道。
  2. 创建一个小型 shell 函数来执行上面的屏障条件,并添加一种包含文件名的方法,我们将其称为sz
  3. 创建一个解析器,读取 fifo 管道,实时查找屏障条件,提取有效载荷并保存在磁盘上,我们称之为rz

所以你会拥有这个。

$ mkfifo something
$ rz something &
$ ssh user@localhost | tee something
host> sz() {
 ...
}
host> sz file1
host> sz file2

此流程(甚至名称)基于调制解调器传输协议,例如调制解调器

答案3

了解主机上运行的程序会有所帮助。如果你使用的是 Linux,

scp user@host:/path/myfile .

应该管用。

答案4

user535759 说得对。对我来说,最后一种解决方案是正确的:在两台机器上安装 lrzsz(已经是一个通用包),然后使用连接。

我太懒了,从来不记得使用 zssh,但有一次我必须连接到一个只能接受一个连接的主机,这是必须的。工作正常。

相关内容