如何从远程 SSH 会话将数据发送到本地剪贴板

Posted

技术标签:

【中文标题】如何从远程 SSH 会话将数据发送到本地剪贴板【英文标题】:How to send data to local clipboard from a remote SSH session 【发布时间】:2010-11-12 05:57:34 【问题描述】:

Borderline ServerFault 问题,但我正在编程一些 shell 脚本,所以我先在这里尝试 :)

大多数 *nixes 都有一个命令,可以让您通过管道/重定向输出到本地剪贴板/粘贴板,并从中检索。在 OS X 上,这些命令是

pbcopy, pbpaste 

在通过 SSH 连接到另一台服务器时是否可以复制此功能?也就是说,

    我正在使用计算机 A。 我打开一个终端窗口 我通过 SSH 连接到计算机 B 我在计算机 B 上运行命令 计算机 B 的输出被重定向或自动复制到计算机 A 的剪贴板。

是的,我知道我可以(颤抖)使用鼠标从命令中选择文本,但我已经习惯了将输出直接传输到剪贴板的工作流程,我希望我的遥控器也一样会议。

代码很有用,但一般方法也很受欢迎。

【问题讨论】:

我在 Linux 上回答了一个类似的问题 here,与 @TrinitronX 类似,但没有 XQuartz。 【参考方案1】:

如果您在 Mac 上使用iTerm2,有一种更简单的方法。此功能通过it2copy 命令内置于iTerm2 的Shell Integration 功能中:

Usage: it2copy
          Copies to clipboard from standard input
       it2copy filename
          Copies to clipboard from file

要使其工作,请在登录远程主机时选择iTerm2-->Install Shell Integration菜单项,将其安装到您自己的帐户中。完成后,您将可以访问it2copy,以及一系列其他提供酷炫功能的别名命令。

这里的其他解决方案是很好的解决方法,但相比之下,这个解决方案非常轻松。

【讨论】:

【参考方案2】:

请允许我添加一个解决方案,如果我没记错的话,之前没有建议过。 它涉及:

    在远程主机上创建一个 fifo 文件。 打开与远程主机的连接和另一个在该 fifo 上并行等待的连接。 您在该 fifo 文件中回显的任何内容最终都会出现在您的本地剪贴板中。 会话完成后,立即终止连接。

它利用 ssh 的 ControlMaster 功能来避免连接开销并为您提供干净的连接终止。

此外,远程主机没有特殊要求(例如 x 个库)。

编辑:根据要求,代码本身:

将以下内容粘贴到您的 bashrc 中并使用 sshx host 进行连接。

在远程机器 echo SOMETHING > ~/clip 上,希望 SOMETHING 最终会出现在本地主机的剪贴板中。

您将需要本地主机上的 xclip 实用程序。

_dt_term_socket_ssh() 
    ssh -oControlPath=$1 -O exit DUMMY_HOST

function sshx 
    local t=$(mktemp -u --tmpdir ssh.sock.XXXXXXXXXX)
    local f="~/clip"
    ssh -f -oControlMaster=yes -oControlPath=$t $@ tail\ -f\ /dev/null || return 1
    ssh -S$t DUMMY_HOST "bash -c 'if ! [ -p $f ]; then mkfifo $f; fi'" \
        ||  _dt_term_socket_ssh $t; return 1; 
    (
    set -e
    set -o pipefail
    while [ 1 ]; do
        ssh -S$t -tt DUMMY_HOST "cat $f" 2>/dev/null | xclip -selection clipboard
    done &
    )
    ssh -S$t DUMMY_HOST \
        ||  _dt_term_socket_ssh $t; return 1; 
    ssh -S$t DUMMY_HOST "rm $f"
    _dt_term_socket_ssh $t

更详细的解释在我的网站上:

https://xicod.com/2021/02/09/clipboard-over-ssh.html

【讨论】:

虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review @radrow 感谢您的评论,我更新了答案【参考方案3】:

如果您正在加班,例如Kubernetes 集群中的一个 pod 而不是直接 SSH,因此您无法进行文件传输,您可以使用 cat 然后将终端输出保存为文本。例如,在 macOS 中,您可以执行 Shell -> Export as text。

【讨论】:

【参考方案4】:

对于任何通过谷歌搜索的人: 这个时代最好的解决方案似乎是lemonade

clipboard-tool的neovim帮助文本中也提到了各种解决方案

【讨论】:

【参考方案5】:

Far Manager Linux port 支持在本地和远程主机之间同步剪贴板。您只需打开本地 far2l,在里面执行“ssh somehost”,在该 ssh 会话中运行远程 far2l,然后让远程 far2l 与本地剪贴板一起工作。

它支持Linux、*BSD和OS X;我创建了一个special putty build 以在 Windows 中使用此功能。

【讨论】:

【参考方案6】:

这个答案在chosen answer 的基础上增加了更多的安全性。

那个答案讨论了一般形式

<command that makes output> | \
    ssh <user A>@<host A> <command that maps stdin to clipboard>

可能缺乏安全性的地方是ssh 权限允许host B&gt; 上的&lt;user B&gt;ssh 进入host A 并执行any 命令。

当然,BA 的访问可能已经被 ssh 密钥所限制,甚至可能有密码。但是另一层安全性可以限制B 可以在A 上执行的允许命令的范围,例如这样rm -rf / 就不能被调用。 (当ssh没有有密码时,这一点尤其重要。)

幸运的是,ssh 有一个称为命令限制强制命令的内置功能。请参阅ssh.com,或 这个serverfault.com question。

下面的解决方案显示了通用表单解决方案以及强制执行的ssh 命令限制

添加了命令限制的示例解决方案

此安全增强解决方案遵循一般形式 - 来自 host-B 上的 ssh 会话的调用很简单:

cat <file> | ssh <user-A>@<host A> to_clipboard

剩下的部分显示了让它工作的设置。

ssh命令限制设置

假设B 上的用户帐户是user-B,并且B 有一个ssh 密钥id-clip,它是以通常的方式创建的(ssh-keygen)。

然后在user-A的ssh目录下有个文件

/home/user-A/.ssh/authorized_keys

识别密钥id-clip并允许ssh连接。

通常authorized_keys每一行的内容就是被授权的公钥,例如id-clip.pub的内容。

但是,为了强制执行命令限制,公钥内容由要执行的命令附加(在同一行上)。 在我们的例子中:

command="/home/user-A/.ssh/allowed-commands.sh id-clip",no-agent-forwarding,no-port-forwarding,no-user-rc,no-x11-forwarding,no-pty <content of file id-clip.pub>

指定命令"/home/user-A/.ssh/allowed-commands.sh id-clip",并且在使用密钥id-clip 启动与host-Assh 连接时执行 - 不管是什么命令写在ssh命令行

该命令表示一个脚本文件allowed-commands.sh,该脚本文件的内容是

#/bin/bash
#
# You can have only one forced command in ~/.ssh/authorized_keys. Use this
# wrapper to allow several commands.

Id=$1

case "$SSH_ORIGINAL_COMMAND" in
    "to-clipboard")
          notify-send "ssh to-clipboard, from $Id"
        cat | xsel --display :0 -i -b
          ;;
    *)
        echo "Access denied"
        exit 1
        ;;
esac

在机器 B 上对 ssh 的原始调用是

... | ssh <user-A>@<host A> to_clipboard

字符串to-clipboard由环境变量SSH_ORIGINAL_COMMAND传递给allowed-commands.sh。 此外,我们从authorized_keys 的行中传递了密钥的名称id-clip,只有id-clip 才能访问。

线

          notify-send "ssh to-clipboard, from $Id"

只是一个弹出消息框,让您知道正在编写剪贴板 - 这可能也是一个很好的安全功能。 (notify-send 适用于 Ubuntu 18.04,可能不适用于其他版本)。

在一行

cat | xsel --display :0 -i -b

参数--display :0 是必需的,因为该进程没有自己的带有剪贴板的X 显示, 所以必须明确说明。这个值 :0 恰好在带有 Wayland 窗口服务器的 Ubuntu 18.04 上工作。在其他设置上它可能不起作用。对于标准 X 服务器this answer 可能会有所帮助。

host-A/etc/ssh/sshd_config参数

最后应该设置主机A上的/etc/ssh/sshd_config中的几个参数,以确保允许连接,并允许使用ssh-key,无需密码:

PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
AllowUsers user-A

sshd服务器重新读取配置

sudo systemctl restart sshd.service

sudo service sshd.service restart

结论

设置起来有点费力,但是除了to-clipboard之外的其他功能可以在同一个框架中并行构建。

【讨论】:

具有远程转发功能的 Xsel 是在本地运行 i3 的 Ubuntu 18.04 上对我有用的唯一答案。无需 X11 转发。【参考方案7】:

ssh 服务器上的反向隧道端口

所有现有的解决方案都需要:

客户端上的 X11(如果有,服务器上的 xclip 效果很好)或 客户端和服务器在同一个网络中(如果您在工作中试图访问您的家庭计算机,则情况并非如此)。

这是另一种方法,但您需要修改通过 ssh 连接到计算机的方式。

我已经开始使用它了,它远没有看起来那么吓人,所以试试吧。

客户端(ssh 会话启动)

ssh username@server.com -R 2000:localhost:2000

(提示:将其设为键绑定,这样您就不必键入它)

客户端(另一个选项卡)

nc -l 2000 | pbcopy

注意:如果您没有pbcopy,则只需将tee 写入文件即可。

服务器(在 SSH 会话内)

cat some_useful_content.txt | nc localhost 2000

其他说明

实际上,即使您正处于 ssh 会话的中间,也有一种方法可以启动隧道,但我不想吓跑人们远离实际上并没有看起来那么糟糕的事情。但是如果我看到任何兴趣,我会在稍后添加详细信息

【讨论】:

+1 -- 非常简洁。但是——当我这样做时,cat some_useful_content.txt | nc localhost 2000 命令似乎挂起。我需要手动 ctr-c 来停止它,只有这样内容才能到达我的客户端剪辑/粘贴板 它会等到有人将另一端的数据出列。 其实我想我误解了你的问题。我不知道为什么会这样。 nc -l -p 对我有用,但只是 nc -l 不行。我也有@AlanStorm 的问题。 我通过指定-c解决了挂网猫的问题。我使用 brew 安装的 GNU netcat。【参考方案8】:

最简单的解决方案,如果您在 OS X 上使用终端,并且您一直在远程服务器中进行 ssh,并希望获取文本文件、日志或 csv 的结果,只需:

1)Cmd-K清除终端输出

2)cat &lt;filename&gt;显示文件内容

3) Cmd-S 保存终端输出

您将手动删除文件的第一行和最后一行,但这种方法比依赖安装其他软件包、“反向隧道”和尝试拥有静态 IP 等要简单一些。

【讨论】:

+1 是我自己使用过的一种有用技术,它确实会迫使您丢失终端历史记录,并且(如前所述)第一行/最后一行问题有点繁琐。 同意@AlanStorm 这种方法更重要的问题是它只会保存终端缓冲区保留的行数。通常这不是问题,但是如果您尝试获取日志文件的内容,那么您可能会耗尽容量, 这是真的@Sridhar-Sarnobat,一般来说这不是一个很好的解决方案。我只是使用scp 将步骤 3 替换为 Cmd-A(全选)和 Cmd-C 以复制到剪贴板。起初,我认为Cmd-A 只会选择可见屏幕的文本,但它确实会选择全部。【参考方案9】:

我最喜欢的方式是ssh [remote-machine] "cat log.txt" | xclip -selection c。当您不想(或不能)从远程 ssh 到本地时,这是最有用的。

编辑:在 Cygwin ssh [remote-machine] "cat log.txt" &gt; /dev/clipboard.

编辑:来自 nbren12 的有用评论:

几乎总是可以使用 SSH 端口转发设置反向 ssh 连接。只需将RemoteForward 127.0.0.1:2222 127.0.0.1:22 添加到本地.ssh/config 中的服务器条目中,然后在远程机器上执行ssh -p 2222 127.0.0.1,然后将连接重定向到本地机器。 – nbren12

【讨论】:

+1:当无法进行反向 SSH 连接时,比其他解决方案容易得多! 这个极其简单的解决方案,你应该得到更多的赞! 对于我们这些使用 Mac OSX 的人,ssh [remote-machine] "cat log.txt" | pbcopy 根据这份报告here,我必须使用cat 才能使其在cygwin Windows 8 上运行:ssh [remote-machine] "cat log.txt" | cat &gt; /dev/clipboard(当然,我的远程命令不是cat;这是流浪虚拟机中的其他东西,所以我实际上运行了vagrant ssh -c "command" | cat &gt; /dev/clipboard) 几乎总是可以使用 SSH 端口转发设置反向 ssh 连接。只需将RemoteForward 127.0.0.1:2222 127.0.0.1:22 添加到本地.ssh/config 中的服务器条目,然后在远程机器上执行ssh -p 2222 127.0.0.1,然后将连接重定向到本地机器。【参考方案10】:

不是单行,但不需要额外的 ssh

必要时安装netcat 使用termbin:cat ~/some_file.txt | nc termbin.com 9999。这会将输出复制到 termbin 网站并将 URL 打印到您的输出中。 从您的计算机访问该 url,您将获得输出

当然,请勿将其用于敏感内容。

【讨论】:

哇,这是一个非常有创意的解决方案。【参考方案11】:

这是我基于 SSH 反向隧道、netcat 和 xclip 的解决方案。

首先在您的工作站上创建脚本(例如,clipboard-daemon.sh):

#!/bin/bash
HOST=127.0.0.1
PORT=3333

NUM=`netstat -tlpn 2>/dev/null | grep -c " $HOST:$PORT "`
if [ $NUM -gt 0 ]; then
    exit
fi

while [ true ]; do
    nc -l $HOST $PORT | xclip -selection clipboard
done

并在后台启动它。

./clipboard-daemon.sh&

在接收到部分数据后,它将开始 nc 管道输出到 xclip 和重生过程

然后开始ssh连接到远程主机:

ssh user@host -R127.0.0.1:3333:127.0.0.1:3333

在远程机器上登录时,试试这个:

echo "this is test" >/dev/tcp/127.0.0.1/3333

然后尝试在您的工作站上粘贴

您当然可以编写包装脚本,先启动 clipboard-daemon.sh,然后再启动 ssh 会话。这就是它对我有用的方式。享受吧。

【讨论】:

这个解决方案是最适合我的。它不是太复杂并且可以正常工作。 我认为最好的解决方案。您不必担心允许存在安全隐患的反向 ssh 连接,并且无限循环是一个不错的选择。【参考方案12】:

@rhileighalmgren 解决方案很好,但是 pbcopy 会烦人地复制最后一个“\n”字符,我使用“head”去掉最后一个字符以防止这种情况:

#!/bin/bash
head -c -1 |  ssh desktop pbcopy

我的完整解决方案在这里:http://taylor.woodstitch.com/linux/copy-local-clipboard-remote-ssh-server/

【讨论】:

pbcopy 并不是要对它复制的内容做出判断,所以它包含你给它的一切是有道理的。【参考方案13】:

找到了一个不需要反向 ssh 连接的绝佳解决方案!

您可以在远程主机上使用 xclip,以及在 OSX 系统上使用 ssh X11 转发和 XQuartz。

设置:

    安装 XQuartz(我使用 soloist + pivotal_workstation::xquartz recipe 完成了此操作,但您不必这样做) 运行 XQuartz.app 打开 XQuartz 首选项 (+,) 确保选中“启用同步”“当剪贴板更改时更新粘贴板” ssh -X remote-host "echo 'hello from remote-host' | xclip -selection clipboard"

【讨论】:

这与ssh remote-host "echo 'hello from remote-host' | pbcopy 有何不同?如果它可以像这样工作,这将是一个很好的答案:ssh -X remote-host 然后在远程主机上:echo 'hello from remote-host' | xclip -selection clipboard @KasperSouren。我相信它确实如你所愿。 ` | xclip` 在双引号内。 在 2016 年,这显然是最好的、简洁的解决方案。忘记其他基于反向 ssh 的解决方案。 有没有办法做到这一点,而它只是一个一次性命令?我想通过 ssh 在交互式会话中登录到我的远程服务器,然后能够任意发送到我的本地剪贴板。这需要反向 ssh 吗? @Kvass:只要您使用-X 通过 SSH 进行 X11 转发,X11 程序就可以通过上面的 XQuartz 设置更新您的剪贴板。一次性命令是为了证明通过echo 通过xclip 向远程主机的剪贴板发送内容确实有效并且应该同步到您的本地SSH 客户端主机。注意@gdw2 说,“| xclip 在双引号内”。因此,它将作为远程服务器上的命令执行以向其剪贴板发送内容。【参考方案14】:

我正在复活这个帖子,因为我一直在寻找相同的解决方案,并且我找到了一个适合我的解决方案。这是对OSX Daily 的建议的小修改。

就我而言,我使用本地 OSX 机器上的终端通过 SSH 连接到 linux 服务器。像 OP 一样,我希望能够仅使用键盘将少量文本从终端传输到本地剪贴板。

解决方案的精髓:

commandThatMakesOutput | ssh desktop pbcopy

在与远程计算机的 ssh 会话中运行时,此命令获取 commandThatMakesOutput 的输出(例如 ls、pwd)并将输出通过管道传输到本地计算机的剪贴板(名称或 IP “桌面”)。换句话说,它使用嵌套 ssh:您通过一个 ssh 会话连接到远程计算机,在那里执行命令,远程计算机通过不同的 ssh 会话连接到您的桌面并将文本放入剪贴板。

它需要将您的桌面配置为 ssh 服务器(我将其留给您和 google)。如果您设置了 ssh 密钥以促进快速 ssh 的使用,最好使用每个会话的密码或任何您的安全需求,这会容易得多。

其他例子:

ls  | ssh desktopIpAddress pbcopy
pwd |  ssh desktopIpAddress pbcopy

为方便起见,我创建了一个 bash 文件来缩短管道后所需的文本:

#!/bin/bash
ssh desktop pbcopy

在我的例子中,我使用了一个特别命名的键

我用文件名 cb 保存它(我的助记符(剪贴板)。将脚本放在路径中的某个位置,使其可执行并瞧:

ls | cb

【讨论】:

我在vim中经常这样。为此,请在可视模式下选择要复制的内容,然后键入::'&lt;,'&gt;w !ssh desktop pbcopy @MikeBrennan 选择文本后,为什么不直接按 cmd+C(或您设置的任何复制键)? ... 像这样,只有当您的桌面具有静态 IP 并且可以从您 ssh 进入的盒子中访问时,它才真正起作用。对我来说从来不是这样。 反过来不是更容易吗? ssh user@remote 'commandThatMakesOutput' |pbcopy 我需要这里描述的-e none ssh 标志:unix.stackexchange.com/questions/210615/…【参考方案15】:

有多种工具可以访问 X11 选项,包括 xclip 和 XSel。请注意,X11 传统上具有多个选择,并且大多数程序对剪贴板和主选择都有一定的了解(它们并不相同)。 Emacs 也可以使用辅助选择,但这种情况很少见,而且没有人真正知道如何处理剪切缓冲区...

$ xclip -帮助 用法:xclip [选项] [文件] ... 访问 X 服务器选择以进行读取或写入。 -i, -in 从标准输入或文件中将文本读入 X 选择 (默认) -o, -out 将选择打印到标准输出(通常用于 管道到文件或程序) -l, -loops 退出前等待的选择请求数 -d, -display X 显示连接到(例如 localhost:0") -h, -help 使用信息 -选择访问(“主要”,“次要”,“剪贴板”或“缓冲剪切”) -noutf8 不要将文本视为 utf-8,使用旧的 unicode -version 版本信息 - 仅无提示错误,在后台运行(默认) - 在前台安静运行,显示正在发生的事情 -详细的运行评论 向 报告错误 $ xsel -帮助 用法:xsel [选项] 操作 X 选择。 默认情况下,如果两者都输出当前选择并且不会修改 标准输入和标准输出是终端(ttys)。否则, 如果标准输出不是终端,则输出当前选择 (tty),如果标准输入,则从标准输入设置选择 不是终端(tty)。如果给出任何输入或输出选项,则 该程序仅在请求的模式下运行。 如果输入和输出都需要,那么前面的选择是 在被标准输入的内容替换之前的输出。 输入选项 -a, --append 将标准输入附加到选择中 -f, --follow 随着标准输入的增长附加到选择中 -i, --input 将标准输入读入选择 输出选项 -o, --output 将选择写入标准输出 操作选项 -c, --clear 清除选择 -d, --delete 请求清除选择并且 拥有它的应用程序删除其内容 选择选项 -p, --primary 对 PRIMARY 选择进行操作(默认) -s, --secondary 对 SECONDARY 选择进行操作 -b, --clipboard 对剪贴板选择进行操作 -k, --keep 不修改选择,但使 PRIMARY 和 SECONDARY 选择仍然存在,即使在 他们在退出时选择的程序。 -x, --exchange 交换 PRIMARY 和 SECONDARY 选择 X 选项 --显示显示名称 指定到 X 服务器的连接 -t 毫秒,--selectionTimeout 毫秒 以毫秒为单位指定超时,在该时间内 必须检索选择。值 0(零) 指定无超时(默认) 其他选项 -l, --logfile 指定分离时记录错误的文件。 -n, --nodetach 不要从控制终端分离。没有 这个选项,xsel会fork成为背景 在输入、交换和保存模式中处理。 -h, --help 显示此帮助并退出 -v, --verbose 打印信息性消息 --version 输出版本信息并退出 请向 报告错误。

简而言之,您应该尝试xclip -i/xclip -oxclip -i -sel clip/xclip -o -sel clipxsel -i/xsel -oxsel -i -b/xsel -o -b,这取决于您想要什么。

【讨论】:

添加到@ephemient 的帖子:为了在远程主机上使用xclip 和xsel,您可以像这样使用X11 转发:ssh -C -X user@remote-host。如果在远程端运行 xclip 似乎不起作用,请确保在远程 /etc/ssh/sshd_config 文件中设置了 X11Forwarding yes。还要确保xauth 安装在远程端。对于无头机器,可以安装xauthxvfb 这是一个description,包含额外的细节以及 vim 键绑定。 @TrinitronX 哦哇——我的头撞到墙上了,感谢xvfb 的提及。我正在运行一个无头服务器,所以 X11 一定没有运行!

以上是关于如何从远程 SSH 会话将数据发送到本地剪贴板的主要内容,如果未能解决你的问题,请参考以下文章

如何在远程 Linux ssh 会话上运行的 vim 中拉到本地 OSX 剪贴板?

当我通过 Git Bash 中的 ssh 在远程 Linux 机器上运行命令时,如何将文件的内容直接复制到我的 Windows 剪贴板中?

如何将服务器上的文件内容复制到本地剪贴板?

如何通过按钮将表单数据作为句子中的变量发送到剪贴板?

从不同的应用程序复制和粘贴剪贴板

从 SSH 会话到远程机器,如何在本地机器上的 Vim 会话中打开文件