在调查中描述的问题时stackoverflow 上的一个问题我将其简化为一个测试用例,证明在非交互模式下 bash 似乎在退出之前清除了 X 系统剪贴板。该测试打开一个 gnome 终端并在其中运行一个 bash 脚本,该脚本将(通过xclip
)一些文本放入 X 系统剪贴板中。当终端打开时,查询剪贴板会返回放置在其中的文本,无论 bash 是以交互模式还是非交互模式运行。但是,在终端关闭后,如果 bash 以交互模式运行,则剪贴板内容会保留下来,但如果 bash 以非交互模式运行,则剪贴板内容会丢失。
$ cat xclip_test
#!/usr/bin/env bash
set -x
gnome-terminal -x bash -i -c "echo abc|xclip -selection clipboard; sleep 3"
sleep 1
xclip -o -selection clipboard
sleep 4
xclip -o -selection clipboard
gnome-terminal -x bash -c "echo 123|xclip -selection clipboard; sleep 3"
sleep 1
xclip -o -selection clipboard
sleep 4
xclip -o -selection clipboard
$ ./xclip_test
+ gnome-terminal -x bash -i -c 'echo abc|xclip -selection clipboard; sleep 3'
+ sleep 1
+ xclip -o -selection clipboard
abc
+ sleep 4
+ xclip -o -selection clipboard
abc
+ gnome-terminal -x bash -c 'echo 123|xclip -selection clipboard; sleep 3'
+ sleep 1
+ xclip -o -selection clipboard
123
+ sleep 4
+ xclip -o -selection clipboard
Error: target STRING not available #!!!!!!!!!!!!!
我使用的是 Ubuntu 16.04,使用默认的 GNU bash ( version 4.3.46(1)-release (x86_64-pc-linux-gnu)
),没有对 bash rc 文件进行自定义。.bash_logout
为了以防万一,我检查了一下,发现有一个对clear_console
实用程序的调用。然而clear_console
似乎不处理剪贴板;此外,该示例不将 bash 作为登录 shell 运行。
这有合理的解释吗?
编辑
gnome-terminal
替换为以下内容时问题仍然存在xterm
:
gnome-terminal -x
... --> xterm -e
...&
而且它并不是唯一的bash
- 它也被复制dash
。
答案1
该书的作者原问题 在 Stackoverflow 上已确定这是 xclip 中的问题。使用xsel
代替xclip
用于操作 X 剪贴板消除了该问题(请注意,仅xclip
当xsel
放置数据进入剪贴板,而不是当读自剪贴板):
$ cat xclip_test
#!/usr/bin/env bash
set -x
xterm -e bash -c "echo abc|xclip -selection clipboard; sleep 3"&
sleep 1
xclip -o -selection clipboard
sleep 4
xclip -o -selection clipboard
$ cat xsel_test
#!/usr/bin/env bash
set -x
xterm -e bash -c "echo abc|xsel --input --clipboard; sleep 3"&
sleep 1
xclip -o -selection clipboard
sleep 4
xclip -o -selection clipboard
$ diff xclip_test xsel_test
3c3
< xterm -e bash -c "echo abc|xclip -selection clipboard; sleep 3"&
---
> xterm -e bash -c "echo abc|xsel --input --clipboard; sleep 3"&
$ ./xclip_test
+ sleep 1
+ xterm -e bash -c 'echo abc|xclip -selection clipboard; sleep 3'
+ xclip -o -selection clipboard
abc
+ sleep 4
+ xclip -o -selection clipboard
Error: target STRING not available # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$ ./xsel_test
+ sleep 1
+ xterm -e bash -c 'echo abc|xsel --input --clipboard; sleep 3'
+ xclip -o -selection clipboard
abc
+ sleep 4
+ xclip -o -selection clipboard
abc
xclip
和两者都xsel
通过从终端分离并生成一个子进程来工作,该子进程负责按需提供选择(直到做出新选择):
$ ps -H
PID TTY TIME CMD
24307 pts/12 00:00:01 bash
27476 pts/12 00:00:00 ps
$ echo qwerty|xclip -selection clipboard
$ ps -H
PID TTY TIME CMD
27481 pts/12 00:00:00 xclip <-- !!!!!!
24307 pts/12 00:00:01 bash
27482 pts/12 00:00:00 ps
问题似乎xclip
是,当从非交互式外壳启动时,它不会完全独立于控制终端,并且会在终端进程退出时终止。
答案2
实际上,不存在X“系统剪贴板”。 X 中的选择由两个 X 客户端合作进行:一个 X 客户端声称它有一个选择(主要、次要、剪贴板),而另一个想要粘贴选择的 X 客户端联系第一个客户端以接收它。
因此,当第一个客户去世时,就没有选择了。然而,我不确定 bash 交互模式如何转换为“终端/bash 仍然可以响应”。做一个ps
可能有助于解决问题。
这同样适用于剪贴板选择,除非xclipboard
您同时运行该程序(或类似的程序),该程序接管提供选择的责任。 (参见例如维基百科文章)。
还有存储为根窗口属性的剪切缓冲区,您可以使用它们来存储永久内容。
答案3
pass
我在 中遇到了同样的问题eshell
。该pass
程序使用xclip
,它以与您提到的相同的方式失败。
我的解决方案是创建一个包装器脚本,该脚本也在xclip
我的 PATH 中 /usr/bin 前面的位置命名,其中包含以下内容:
#!/bin/sh
exec setsid /usr/bin/xclip "$@"
答案4
我使用 xclip -i 遇到了这个或类似的问题。脚本结尾为
echo $totp | xclip -i -r
在 shell 提示符下可以正常运行,但是当脚本用于命令替换时,
totp=$(get-totp)
xclip 会挂起。关闭它的标准输出可以解决这个问题:
echo $totp | xclip -i -r >&-