Bash

xclip 在互動式和非互動式 shell 中的工作方式不同

  • December 2, 2021

在調查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

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似乎是,當從非互動式 shell 啟動時,它不會完全獨立於控制終端並在終端程序退出時死亡。

實際上,沒有 X“系統剪貼板”。X 中的選擇由兩個合作的 X 客戶端工作:一個 X 客戶端聲稱它有一個選擇(主要、次要、剪貼板),另一個想要粘貼選擇的 X 客戶端聯繫第一個客戶端接收它。

因此,當第一個客戶死亡時,就沒有選擇了。但是,我不確定 bash 互動模式如何轉換為“終端/bash 仍然可以響應”。做一個ps可能有助於解決問題。

這同樣適用於剪貼板選擇,除非您同時執行程序xclipboard(或類似程序),它負責提供選擇。(參見例如維基百科文章)。

還有一些作為根視窗屬性儲存的剪切緩衝區,您可以使用它來儲存永久內容。

引用自:https://unix.stackexchange.com/questions/316715