スクリプトから端末を識別する方法は?


8

また、「$TERM」とは言わないでくださいxterm。常にそうです。

bashスクリプトは、どの端末で実行されているか、具体的にはiTerm、Terminal.app、または実際にxtermであるかをどのように確認できますか?

resetTerminal.appとiTerm2でそのままでは機能しないのでお願いします。ただし、iTerm2はターミナルリセット(\x1b]50;ClearScrollback\x07)を実行するためのエスケープシーケンスを認識し、それを検出できた場合resetは、正しいことを行うエイリアスでオーバーライドできます。AFAICT、Terminal.appにはリセットシーケンスがなく、人々はとんでもないtom-hackeryを使ってハッキングします。

ここでの私の最終目標はreset、OS XとLinuxのどちらで作業していても、SSHを介してローカルでもリモートでも同じように作業することです。(私はどちらを覚えようとする必要はありません。そうすることは有用でありreset && command-that-outputs-a-bunch、上手に作業することができます。)Terminal.appとiTermは、reset正しく実装されていないため、この計画でレンチを投げています。

つまり、単にオーバーライドするだけでresetは十分ではありません。Linuxマシンを使用しているgnome-terminal場合、正しいエスケープシーケンスを送信するには、使用しているのがiTerm かを知る必要があります。

ioctl端末が本当に何であるかを尋ねる方法はありますか?

thisこの質問の目的のために、リセットは画面をクリアし、カーソルをリセットして、スクロールバックバッファーをワイプする必要があります。


まあ、これはバグではなく機能なので、彼らは言う。Terminal.appの設定、ターミナルタブを開き、スクロールバック行を0に設定するとどうなりますか?現在の行の上にあるテキスト、または画面の上部にあるテキストをすべて無効にしますか?私が知っている、それはあなたが要求したものと正確には同じではない、一撃の価値がある。
nitro2k01 2013

@ nitro2k01:それが何を成し遂げるかわかりませんか?私が欲しいスクロール。私はそれを時々、そしてできればでクリアできるようにしたいだけです。それはreset私の指が知っているからです。
Thanatos

「リセット」の問題については、明確にするために、resetコマンドがターミナルエミュレータのスクロールバックコンテンツをクリアすることを期待していますが、それが保証されるわけではありません。スクロールバックはターミナルエミュレータ固有の機能であり、実際には端末の一部。ただし、ターミナルはスクロールバックを消去するためにED(ディスプレイ内消去)エスケープシーケンスの拡張をサポートしていESC [ 3 Jます。画面をクリアして、それを使用できます。たとえば、reset && printf '\e[3J’
Chris Page

Erase in Display拡張機能の詳細については、ここのapple.stackexchange.com/a/113168/6883を参照してください。
Chris Page

@ChrisPage:端末は風変わりなものであることを理解していますが、自分がxterm(を介してTERM=xterm)であると宣言した場合は、リセット時にスクロールバックをクリアするXTermのスーパーセットをエミュレートすると思います。(まるで「青」のエスケープシーケンスを送信したかのように、青を期待します)確かに、私のxtermはErase is backspace.それを教えてくれます。それはただ迷惑です。
タナトス2014年

回答:


10

を使用し$TERM_PROGRAMます。

iTermはそれをiTerm.appに設定し、Terminal.app はに設定しApple_Terminalます。


ええ、OK、これは明らかに私のハックよりも優れています、+ 1 :)。ハックは、これら2つだけでなく、どのターミナルエミュレータでも機能するはずです。
terdon 2013

すべての端末エミュレータを検出する単一の方法はありません。xtermの場合、たとえば、$ XTERM_VERSION変数を確認できます。それはおそらくOS X上の3つの最も人気のエミュレータであるかの世話をします
クリス・ページ

良いスタートなので、これを受け入れる。残念ながら、この変数はSSHセッション内では使用できないため、それほど簡単ではありません。転送するために編集できる設定があると思います。
タナトス2014年

1
@Thanatosはsshd_config「S AcceptEnvたぶん。これ(あなたのシェルはあなたのターミナルが走っているものとは異なるホストで走っている)は非常に重要な情報なので、それは本当に問題の一部であるべきです。
ダニエルベック

@DanielBeck:厳密にはそうではありません。ローカルでもリモートでも同じようにしたいのですが。私がしようとしているのは、ターミナルに「リセット」と入力すると、ローカルまたはリモートで作業しているOS XとLinuxのどちらを使用しているかに関係なく、ターミナルがリセットされることです。これを質問に編集しました。
タナトス2014年

1

$TERM現在実行中のターミナルエミュレータとは何の関係もありません。これはデフォルトのターミナルであり、何にでも設定できます。実行中のターミナルエミュレータの名前を取得するには、を使用psして、現在のシェルの親プロセスのPIDを取得できます。

注:以下はOSXでは失敗しますが、Linuxでは問題なく動作します。

現在のシェルプロセスのPIDは$$です。そこから、を使用psしてプロセスツリーを表示し、現在のシェルセッションの親のPIDを出力できます。

ps -axjf | awk -v pid=$$ '($2==pid){print $1}'

次に、そのPIDを渡してps、コマンド名を出力するように指示できます。

ps -o comm=  $(ps -axjf | awk -v pid=$$ '($2==pid){print $1}')

これは名前を切り捨てます。それを理解するには十分なはずですが、スクリプトには適さない可能性があります。完全な名前を取得するには、

ps --no-headers $(ps -axjf | awk -v pid=$$ '($2==pid){print $1}') | awk '{print $NF}'

これは、いくつかの異なる端末を使用してシステムで取得するものです。

  1. terminator

    $ ps --no-headers $(ps -axjf | awk -v pid=$$ '($2==pid){print $1}') | 
       awk '{print $NF}'
    /usr/bin/x-terminal-emulator
    
  2. gnome-terminal

    $ ps --no-headers $(ps -axjf | awk -v pid=$$ '($2==pid){print $1}') | 
       awk '{print $NF}'
    /usr/lib/gnome-terminal/gnome-terminal-server
    
  3. xterm

    $ ps --no-headers $(ps axjf | awk -v pid=$$ '($2==pid){print $1}') | 
       awk '{print $NF}'
    xterm
    

OS Xでは動作しません:ps: illegal option -- f
ダニエルベック

@DanielBeckはBSDスタイルだ、ありがとう。更新されたバージョンでもう一度お試しいただけますか?-beforeオプションを追加すると、OSXに従って動作するはずman psです。
terdon 2013

より良いですが、まだ機能しません。出力形式は異なり(PIDは$2、PPIDは$3)、シェルの親プロセスはlogin(ターミナル設定に応じて)異なるパラメーターを持つ場合があります。ただし、その親プロセスはTerminalです。--no-headers存在しない場合は、のようなものが必要になりますtail -n1。また、UIのあるすべてのプロセスには引数-psn_0_...があるため、awk '{print $NF}'機能しません。
ダニエルベック

@DanielBeckはその時はよくない。わかりました。OSXではこれが失敗することを明確にします。
terdon 2013

これはローカルでのみ機能することに注意してください。このアプローチを使用して、リモートクライアントで使用されているターミナルエミュレータを特定することはできません。最良の答えは、$ TERM_PROGRAM(@DanielBeckの答えで述べたとおり)や$ XTERM_VERSIONなどの変数を探して、エミュレータアプリケーションを推定することです。
Chris Page

0

親プロセスの名前またはパスを取得するポータブルな方法を次に示します。

iTerm 2:

$ ps -p $(ps -p $$ -o ppid=) -o comm=
/Applications/iTerm.app/Contents/MacOS/iTerm

Ubuntuのgnome-terminal:

$ ps -p $(ps -p $$ -o ppid=) -o comm=
gnome-terminal

Terminal.app:

$ ps -p $(ps -p $$ -o ppid=) -o comm=
login

Terminal.appがデフォルトのログインシェルで新しいシェルを開くように設定されている場合、シェルの親プロセスはターミナルではなくであることに注意してくださいlogin

このcomm列は、OS Xのコマンドの完全パスであり、Linuxのprocps実装ではコマンド名が15文字に切り捨てられています。


iTermで試してみましたlogin-コマンドを実行するためにプロファイルをカスタマイズしましたlogin -fp danielbeckか?
Daniel Beck
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.