ssh 命令不会终止

ssh 命令不会终止

我编写了一个脚本来从我的 Android 手机设置我的桌面剪贴板。

#!/bin/sh

ssh -Y user@host "export DISPLAY=:0; echo -n $(termux-clipboard-get) | xclip -selection clipboard"

脚本按预期运行,但并未终止。我必须按Ctrl+C才能返回提示。

我已使用此-f选项并立即返回。来自man ssh

-f
请求ssh在命令执行前转至后台。如果ssh要询问密码或口令,但用户希望在后台执行,则此功能很有用。[…]

我不确定这是否是解决这个问题的正确方法。它不需要在后台运行。它只需要执行命令并返回。

为什么我的没有ssh返回?有ssh -f好办法吗?还有更好的办法吗?

答案1

这个答案

X 中的选择功能通过两个 X 客户端的协作来实现:一个 X 客户端声称它有一个选择(主要、次要、剪贴板),另一个想要粘贴该选择的 X 客户端将联系第一个客户端来接收该选择。

在您的例子中,原始节点xclip死亡,但其子节点幸存下来,声称它拥有选择权,并为将来想要粘贴的客户端提供服务。它似乎没有完全分离,SSH 服务器等待它退出;所以您的ssh客户端等待它退出。因此需要Ctrl+ C

稍后,如果另一个客户端声称它有选择,则远程xclip将退出并解锁您的本地ssh。这意味着您的解决方法-f并不那么糟糕:后台进程不会累积,最多只会有一个停滞ssh

链接的答案试图解决一个看似有些相关的问题。另一个答案那里有建议xsel。事实上,在我的测试中,这并没有阻止:

ssh -Y user@host "export DISPLAY=:0; echo -n foobar | xsel -i -b"

更改xclipxsel至关重要。但您原来的命令还可以进一步改进。

  • 我认为你不需要-Y(或),因为远程命令不与本地 X 服务器交互。只需将right 设置为指向所需的显示-X即可DISPLAYxsel当地的xsel

  • 不需要export。变量仅与相关xsel,因此此代码片段应该足够了:DISPLAY=:0 xsel -i -b

  • 严重缺陷。 $(termux-clipboard-get)在本地进行扩展,无论你从哪里获得什么,termux-clipboard-get都将嵌入到你传递给远程 shell 的字符串中,以便解释作为代码。

    例如,如果termux-clipboard-get返回; rm -f /very/important/file; true,则远程 shell 将运行

    export DISPLAY=:0; echo -n ; rm -f /very/important/file; true | …
    

    你知道它的作用吗?正确的做法是通过管道传输到ssh

    termux-clipboard-get | ssh user@host 'DISPLAY=:0 xsel -i -b'
    

    这样,输出将termux-clipboard-get永远不会被视为代码。

  • 我猜你故意习惯于不带任何尾随换行符echo -n来获取输出。如果是这样,你应该在本地删除尾随换行符,然后termux-clipboard-get不依赖echo

    printf '%s' "$(termux-clipboard-get)" | …
    

最终形式可以是:

printf '%s' "$(termux-clipboard-get)" | ssh user@host 'DISPLAY=:0 xsel -i -b'

请注意,该命令会删除尾随换行符,即使数据应被解释为二进制且不可更改。NUL 字符也会出现问题。如果您需要逐字传递某些数据,则只需直接从管道传递termux-clipboard-get

termux-clipboard-get | ssh …

相关内容