![ssh 命令不会终止](https://linux22.com/image/1627340/ssh%20%E5%91%BD%E4%BB%A4%E4%B8%8D%E4%BC%9A%E7%BB%88%E6%AD%A2.png)
我编写了一个脚本来从我的 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"
更改xclip
为xsel
至关重要。但您原来的命令还可以进一步改进。
我认为你不需要
-Y
(或),因为远程命令不与本地 X 服务器交互。只需将right 设置为指向所需的显示-X
即可DISPLAY
xsel
当地的到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 …