ターミナルからGUIを起動するときに煩わしさを解消する方法は?


14

グラフィカルデスクトップを使用するよりも、ターミナルウィンドウからGUIアプリケーションを起動することを好みます。頻繁に迷惑なのは、開発者がこのタイプの使用を予期していないことが多いため、アプリは多くの役に立たない、不可解な、または情報のないメッセージをstdoutまたはstderrに出力することです。バックグラウンドでプログラムを実行し、&を付けてジョブの作成と終了のレポートを生成するため、ターミナルでさらに混乱が生じます。

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

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

回答:


15

標準エラーをすぐにリダイレクトすること/dev/nullは、早期のエラーメッセージを非表示にし、失敗を診断するのが難しいため、悪い考えです。次のstart-appzshスクリプトのようなものをお勧めします。

#!/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 ...

このスクリプトは、最大10行のメッセージを最大5秒間出力します。ただし、アプリケーションがすぐにクラッシュする場合(セグメンテーション違反など)、エラーメッセージは表示されないことに注意してください。もちろん、このスクリプトをさまざまな方法で変更して、必要なことを行うことができます...

注:start-appzshで補完を機能させるには、次の操作で十分です。

compdef _precommand start-app

そしてbashで:

complete -F _command start-app

(のための1つからコピーexectime/usr/share/bash-completion/bash_completion)。


6
かわいいアイデア、+ 1。しかし、GUIアプリからstderrをリダイレクトすることは一般的に悪い考えだとは思いません。すべてのユーザーの99%がグラフィカルデスクトップから呼び出すため、stderrに送られたものは一切表示されません。ソフトウェアは、GUIを介してエラーを報告するように設計されています。stdoutとstderrに表示されるのは、通常、開発者がだれもそれらを見るとは思わなかったために気にすることのないデバッグメッセージです。
ベンクロウェル14

@BenCrowell GUIアプリはGUIを介してエラーを報告することに同意しますが、場合によっては、GUIを起動する前にアプリケーションが失敗することがあります。これは、特に、引数を解析するラッパースクリプトを介してアプリケーションが呼び出されたときに発生します(一般に、この場合、引数は正しいはずなので、これはデスクトップからアプリを起動するユーザーにとっては問題ではありません)。
vinc17 14

@BenCrowellまた、$DISPLAY設定されていない場合(たとえば、ユーザーが-Xsshを忘れた場合)またはX認証の問題(unix.stackexchange.com/questions/108679
...-vinc17

@mikeservさまざまなユーザーが(OPだけでなく)この質問に興味を持ち、bashまたはzshを使用する可能性があると思います。zshとbashでの補完に関するメモを追加しました。ご覧のとおり、これは簡単です。
vinc17

@mikeserv日付にテストがあることに注意してください。シンプルで移植性は高いが、機能を追加したい場合は柔軟性が低くなります"$@" 2>&1 | { quit=$(($(date +%s)+5)); while read line && [ $(date +%s) -lt $quit ]; do printf "[%s] %s\n" "$(date +%T)" "$line"; done; } | head -n 10 &(最も重要な点は、実際の実装ではなくアイデアでした)。
vinc17 14

5

この答えはbash向けです。例として、evPDFビューアーEvinceを起動するための便利なコマンドを作成するために、.bashrcで行うことを次に示します。

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

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

ev foo.pdf

(これはエイリアスとは異なるメカニズムであり、優先順位は低くなります。)Evinceのstdinおよびstdoutへの出力は、bitbucket(/ dev / null)に送信されます。アンパサンドは、ジョブをバックグラウンドに配置します。コマンドをかっこで囲むと、サブシェルで実行され、バックグラウンドジョブの作成または完了に関するメッセージが出力されなくなります。

私の.bashrcの2行目は、bashの完全な関数を使用して、evコマンドの引数がpdfの拡張子を持つファイルであることをbashに伝えます。これは、ディレクトリに座っているfoo.tex、foo.auxなどのファイルもある場合、タブキーを入力して押すことができev foo、bashがファイル名をfoo.pdfとして入力することを知っていることを意味します。


1
ベン、あなたが知っているように、あなたは少し機能をやりすぎているかもしれません。それは偉大な答えだと私はQ&upvoteが初めてだったが...考える-悪気は意味しないev() (evince "$@" >&2 &) 2>/dev/null
mikeserv

またはev() (evince "$@" &>/dev/null $)
グレンジャックマン14

@glenn:提案の最後から2番目の文字がであると考えていたと思います&
G-Manが「Reinstate Monica」と言う14

はい、まったくその通りです。
グレンジャックマン14

5

別の可能性は使用することですcommand降格するexecから特別のような昔ながらの組み込みに組み込み:

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

だから今できること:

(shh; call some process &)

私はちょうどそれcommandzsh (他のほとんどのシェルで動作するように)では動作しないことに気づきましたが、動作しない場合は代わりに行うことができます:

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アプリのコンソール出力のほぼすべてが、一般にXのtty(コンソール)を対象としていることは注目に値します。ファイルXからアプリを実行するX .desktopと、生成される出力はXの仮想端末にルーティングされますX。これは、最初に起動したttyでした。このtty番号はで対処できます$XDG_VTNR

不思議なことに、そしてたぶん私が使い始めたからかもしれませんstartx-私はもはや書くだけではないようです/dev/tty$XDG_VTNR。これもあり(私は可能性が高いと思いとして)で実装は非常に最近の急激な変化に何か持っているXorg、それがもとで実行することができますv1.16 systemdというよりも、必要なユーザーセッションルート権限を。

それでも、私は行うことができます:

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

(gui; some x app &)

これで、すべてsome x appのコンソール出力が/dev/tty$((1+$XDG_VTNR))my xtermのpty ではなくにルーティングされます。この最後のページはいつでも取得できます:

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

とにかく出力をログに記録するためにいくつかの仮想端末を専用にすることはおそらくベストプラクティスです。/dev/console一般的には既にこのために予約されていますが、あなたはchownそれを気楽に書くために必要な可能性が高いことをしないことを好むかもしれません。あなたはあなたができることを可能にするいくつかの機能を持っているかもしれませんprintk-それは基本的に印刷しています/dev/console-それで私が思うようにそれを使うことができます。

これを行う別の方法は、そのような目的にptyを捧げることです。たとえば、xtermウィンドウを開いたままにして、ttyそこから実行されるときの出力を環境変数に保存し、その値をgui出力の宛先として使用できます。このようにして、すべてのログが個別のログウィンドウにルーティングされ、必要に応じてスクロールできます。

あなたが興味を持っているなら私はかつてbash歴史で同様のことができるかについての答えを書きまし


1
echo $?役に立たない情報を追加し、bashのバグに基づいているため、出力に関するコメントを削除することをお勧めします。bashのバグは、ここで報告したばかりです。08 / msg00081.htmlおよびDebian BTS:bugs.debian.org/cgi-bin/bugreport.cgi
bug=

@ vinc17うん-私はそれを奇妙なbashでやったに違いない-私はそのシェルを使用しないので。私はこの答えだけだと思います。
mikeserv 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.