web-dev-qa-db-ja.com

xclipは、インタラクティブシェルと非インタラクティブシェルで動作が異なります

stackoverflowでの質問 で説明されている問題を調査している間、非対話型モードではbashが終了する前にXシステムクリップボードをクリアするように見えることを示すテストケースに簡略化しました。このテストでは、gnomeターミナルを開き、その中でbashスクリプトを実行して、Xシステムクリップボードにテキストを(xclip経由で)配置します。ターミナルが開いているときにクリップボードにクエリを実行すると、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            #!!!!!!!!!!!!!
_

私はUbuntu16.04を使用しており、デフォルトのGNU bash(version 4.3.46(1)-release (x86_64-pc-linux-gnu))を使用しており、rcファイルをbashにカスタマイズしていません。念のため_.bash_logout_を確認し、呼び出しを見つけました。 _clear_console_ユーティリティに。ただし、_clear_console_はクリップボードを処理していないようです。さらに、この例ではbashをログインシェルとして実行していません。

これは理にかなった説明があるものですか?

[〜#〜]編集[〜#〜]

_gnome-terminal_をxtermに置き換えても、問題は解決しません。

_gnome-terminal -x_...->_xterm -e_..._&_

また、bashに固有のものではありません。dashでも再現されます。

5
Leon

元の質問 Stackoverflowの作者 これはxclipの問題であると特定されました 。 Xクリップボードの操作に xsel の代わりに xclip を使用すると、問題が解消されます(xclipxselに置き換えられたのは、データを配置する場合のみクリップボードに挿入します。クリップボードからを読み取るときではありません):

$ 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

xclipxselはどちらも、ターミナルから切り離し、オンデマンドで選択を提供する子プロセスを生成することで機能します(新しい選択が行われるまで)。

$ 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の問題は、非対話型シェルから起動した場合、制御端末から完全に独立せず、端末プロセスが終了すると停止することです。

3
Leon

実際には、Xの「システムクリップボード」はありません。 Xでの選択は、協力する2つのXクライアントによって機能します。1つのXクライアントは、選択(プライマリ、セカンダリ、クリップボード)があると主張し、選択を貼り付けたい別のXクライアントは、最初のクライアントに連絡してそれを受け取ります。

したがって、最初のクライアントが死んだとき、選択はありません。ただし、bashインタラクティブモードが「端末/ bashは引き続き応答可能」にどのように変換されるかはわかりません。 psを実行すると、問題が解決する場合があります。

同じことがクリップボードの選択にも当てはまります。ただしプログラムxclipboard(または同様のプログラム)を同時に実行すると、選択を提供する責任が引き継がれます。 (たとえば、 wikipedia の記事を参照してください)。

ルートウィンドウのプロパティとして保存されるカットバッファもあり、永続的なコンテンツを保存するために使用できます。

2
dirkt