端末でGUIを起動したときに発生する不快感をどのように排除できますか?

端末でGUIを起動したときに発生する不快感をどのように排除できますか?

私は、グラフィックデスクトップを使用するよりも、ターミナルウィンドウでGUIアプリケーションを起動する方が好きです。一般的な苦情は、開発者がこのタイプの使用を予期しないことが多いため、アプリケーションがstdoutまたはstderrに役に立たない、秘密、または情報のないメッセージを一括印刷することです。 & を使用してバックグラウンドでプログラムを実行すると、ジョブの作成と終了に関するレポートが生成されるため、端末でさらに混乱が発生します。

コマンドライン引数を受け入れてオートコンプリートを処理するこれらの問題の回避策は何ですか?

関連:https://stackoverflow.com/questions/7131670/make-bash-alias-that-takes-parameter

答え1

標準エラーを直ちにリダイレクトすることは、以前の/dev/nullエラーメッセージを隠してエラーを診断するのが難しいかもしれないので、悪い考えです。次のzshスクリプトを使用することをお勧めしますstart-app

#!/usr/bin/env zsh
coproc "$@" 2>&1
quit=$(($(date +%s)+5))
nlines=0
while [[ $((nlines++)) -lt 10 ]] && read -p -t 5 line
do
  [[ $(date +%s) -ge $quit ]] && break
  printf "[%s] %s\n" "$(date +%T)" "$line"
done &

ただ実行してみてください:start-app your_command argument ...

スクリプトは最大5秒間最大10行のメッセージを出力します。ただし、アプリケーションが直ちにクラッシュした場合(たとえば、分割エラーのため)、エラーメッセージは表示されません。もちろん、必要に応じてこのスクリプトをさまざまな方法で変更できます。

注:zshで補完機能を使用するには、start-app次のようにします。

compdef _precommand start-app

バッシュから:

complete -F _command start-app

(でおよびexecからtimeコピー/usr/share/bash-completion/bash_completion)。

答え2

この答えはbashについてです。たとえば、evPDFビューアEvinceを起動する便利なコマンドを作成するために.bashrcで実行した操作は次のとおりです。

ev() { (evince "$1" 1>/dev/null 2>/dev/null &) }
complete -f -o default -X '!*.pdf' ev

最初の行は関数を定義しますev。コマンドラインで関数を使用すると、関数名は次のように認識されます。

ev foo.pdf

(これはエイリアスとは異なるメカニズムであり、優先度が低いです。)stdinとstdoutへのEvinceの出力はbitbucket(/ dev / null)に送信されます。 &記号はタスクをバックグラウンドに残します。コマンドを括弧で囲むと、そのコマンドはサブシェルで実行されるため、バックグラウンドジョブの作成または完了に関するメッセージは印刷されません。

私の.bashrcの2行目はbashのフル機能を使用して、evコマンドの引数がpdf拡張子を持つファイルでなければならないことをbashに伝えます。これは、私のディレクトリにfoo.tex、foo.auxなどのファイルもある場合、ev fooTabを入力して押すと、bashがファイル名をfoo.pdfに完成することがわかります。

答え3

commandもう1つの可能性はダウングレードを使用することです。exec特別な次の一般的な既存の組み込み機能に組み込み:

alias shh='command exec >/dev/null 2>&1'

これで、次のことができます。

(shh; call some process &)

commandこれだけがうまくいかないことがわかりました。zsh (ほとんどの他のシェルと同様)しかし、うまくいかない場合は、次のようにすることができます。

alias shh='eval "exec >/dev/null 2>&1"'

...これはどこでも機能します。

実際には、次のようにすることもできます。

alias shh='command exec >"${O:-/dev/null}" 2>&1'

だからあなたはこれを行うことができます:

O=./logfile; (shh;echo can anyone hear &)
O=; (shh; echo this\? &)
cat ./logfile

出力

can anyone hear

@vinc17のコメントについて議論した後、ほぼすべてのGUIアプリケーションのコンソール出力は通常Xstty(対応するコンソール)用であることに注意する価値があります。ファイルXからアプリケーションを実行すると、X .desktop生成された出力はX仮想端末にルーティングされます。これはX最初に始まったttyです。このtty番号を使用してアドレスを指定できます$XDG_VTNR

しかし、奇妙なことに - ちょうど使い始めたのかstartx- これ以上書くことはできないようです/dev/tty$XDG_VTNR(私の考えでは、その可能性が高いと思います)v1.16で最近実装された主な変更に関連して、要件の代わりにXorgユーザーセッションで実行できます。systemd特権。

しかし、私はこれを行うことができます:

alias gui='command exec >/dev/tty$((1+$XDG_VTNR)) 2>&1'

(gui; some x app &)

これで、すべてのコンソール出力が私のptyの代わりsome x appにルーティングされます。次のようにいつでも最後のページを取得できます。/dev/tty$((1+$XDG_VTNR))xterm

fmt </dev/vcs$((1+$XDG_VTNR))

いずれにせよ、最良の方法は、出力ロギングにのみいくつかの仮想端末を使用することです。これは通常これのためにすでに予約されていますが、この記事を幸せにするために必要なことをしたく/dev/consoleないかもしれません。おそらく基本的に印刷をchown行うことができる機能があるでしょうので、そのように使用することが可能だろうと思いました。printk/dev/console

これを行う別の方法は、具体的にフーティこの目標を達成します。たとえば、xtermウィンドウを開いたままにして実行結果を環境変数に保存し、その値をtty出力先として使用できます。guiこれにより、すべてのログが別々のログウィンドウにルーティングされ、必要に応じてスクロールできます。

私が一度書いたことがある回答bash興味があれば、歴史と似たようなことをする方法を学ぶことができます。

関連情報