私はUbuntuでC ++アプリケーションを開発しており、出力を複数の端末にブロードキャストする必要があります。たとえば、C ++アプリケーションでbashコマンドを呼び出して出力を適切な端末に送信するなど、プログラムでこれを行う必要があります。また、開発された「マルチターミナル」ツール(ターミネーターや他のツールなど)をインストールすることはできません。代わりに、標準のbashコマンドを使用する必要があります。
だから:
process A -> will show its output in terminal A.
process B -> will show its output in terminal B.
process C -> will show its output in terminal C.
それから注意してください:
- 複数の端末に同時に様々な情報を放送し、特定の端末に特定の情報を放送します。
- エアクラック作業を見たことがありますか?このアプリケーションは、3つの異なる端末を同時に表示し、各端末は画面の特定のx、y座標に配置され、各端末は異なる情報を表示したことを覚えています。まあ、それは私が必要だと思います。
ナビゲーション後、次の「gnome-terminal」コマンドを見つけて、3つの端末を実行するように調整しました。
gnome-terminal --geometry=45x20+10+10; gnome-terminal --geometry=45x20+505+10; gnome-terminal --geometry=45x20+950+10
いくつかの詳細:
- 端末がgnome端末である必要はありません。 Ubuntuは基本的にxtermsを提供するシンプルなコンソールです。
- 上記のコマンド例のように、一度に3つの端末を起動する必要はありません。ただし、そのプロセスが端末にブロードキャストする必要がある場合は、端末を開いている必要があります。
- プログラムは、出力をブロードキャストする端末をどのように知ることができますか?たぶん端末のpidが使用されていますか?もしそうなら、端末pidはありますか?出力をその端末にどのようにリダイレクトしますか?
たとえば、次のように各端末のpidを取得しようとします。
gnome-terminal --geometry=45x20+10+10 &
私はpidを変数にリダイレクトする方法を探しています(まだ見つかりませんでした...)。
答え1
Unixセッションは、開始点になる必要があるTTYによって処理されます。これらすべてのセッションで同じユーザーアカウントを使用している場合は、必要なTTYに直接出力を送信できる必要があります。
したがって、出力に使用したいさまざまなTTYを使用してプログラムを呼び出すと、そのTTYを出力用に開くことができます。私はGentooとCentosで何の問題もなく試しました。
セッションのTTYを見つけるには、次のtty
コマンドを使用します。
私が好むもう1つのオプションは、クライアント端末がサーバープロセスに接続するクライアント - サーバーアプローチを使用することです。これは、他のユーザーを処理するときのセキュリティへの影響が少ないためです。これは、3つの出力端子のそれぞれに名前付きパイプを使用するのと同じくらい簡単です。
答え2
端末エミュレータを開いてデータを送信すると、ユーザーのデフォルトシェルもそこでbash
実行される可能性が高いことを認識する必要があります。これにより、ユースケースでは望ましくない可能性があるいくつかの結果が得られます。プロンプトによって、出力の最初の列が誤ってソートされます(注意深く画面を消去しない限り)。ユーザーが何を入力しても、画面がより複雑になり、より重要なのはシェルコマンドで実行されることです。特に、ユーザーはもはやプロンプトを見ることができないので、誤解を招く可能性があります。また、端末からデータを読み取ろうとした場合でも、安定して実行することはできません(シェルに到達してもアプリケーションに到達してもキーを押すたびにランダムに実行されます)。
あなたの質問の文脈を正しく理解したら、これはあなたにはお勧めできません。開こうとする端末は、アプリケーションの出力を表示するためにのみ使用する必要があり、同時にシェルを実行しないでください。したがって、デフォルトのシェルの代わりに起動するカスタムコマンドを指定する必要があります。このカスタムコマンドは、tty
端末の行番号(コマンドの出力)をアプリケーションに送り返す簡単なスクリプト(またはC ++ユーティリティ)であり、一部の端末と信号の設定(ローカルエコーオフ()オフstty
、無効)を変更するかもしれません。信号)(stty
またはtrap
))、そして最後に巨人に入りますsleep
。
tty番号をデフォルトのアプリケーションに再送信する方法はいくつかあります。これらの端末とその中にあるスクリプトを起動することは、アプリケーションの観点からは非同期です。たとえば、tty
固定ファイル名を持つ一時ファイルに出力を配置する場合は、アプリケーションが以前のバージョンのファイルを早く読みすぎないようにする必要があります。たとえば、毎回一意の任意のファイル名を作成し、その名前がデフォルトのアプリケーションに表示されるのを待つことができます。
これに対してまったく異なる考え方を提案します。
gnome-terminal(そしてすべてではありませんが、他のほとんどのGtk +ベースの端末エミュレータ)の実際の端末エミュレーションはVTEウィジェットによって行われます。 Gtk+ツールキットを使用してアプリケーションを作成する場合、VTEウィジェットを追加するのはチェックボックスを追加するのと同じくらい簡単です。
gnome-terminal
VTEなど、必要なものを使用する代わりに、アプリケーション自体に複数のVTEウィジェットがあるグラフィックウィンドウ、または内部にVTEを持つ複数のグラフィックウィンドウが表示されることがあります。xterm
あるいは、実際のアプリケーションがGtk +に依存したくない場合は、このタスク用の別々の小さなヘルパーアプリケーションを簡単に作成できます(C / C ++の代わりにPythonを使用することを検討することもできます)。
この場合、シェルはデフォルトでは起動しません(vte_terminal_spawn_sync()
必要な方法を使用して明示的にこれを行う必要があります)。ターミナルラインを取得してvte_pty_get_fd()
文字列に変換してから、ptsname()
メインアプリケーションに戻すだけです。または、単一のアプリケーションでこれを行うと、vte_terminal_feed()
表示したいデータを表示できます。
答え3
問題は簡単なはずです。次のように、ユーザー名と端末名を提供するw
リストを取得します。who
$ w
19:34:00 up 7:17, 5 users, load average: 0.14, 0.08, 0.06
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
tom pts/1 michener:S.0 14:07 3:21m 15.16s 15.08s vile /tmp/foo
tom pts/4 michener:S.1 12:34 2.00s 0.22s 0.00s w
tom pts/5 michener:S.2 13:00 9:48 3.13s 2.79s vile /usr/build
thomas :0 19:32 ?xdm? 47.31s 0.34s fvwm2 -f /usr/b
thomas pts/3 :0 19:33 7.00s 0.04s 0.04s bash
$ who
tom pts/1 2016-06-04 14:07 (michener:S.0)
tom pts/4 2016-06-04 12:34 (michener:S.1)
tom pts/5 2016-06-04 13:00 (michener:S.2)
thomas :0 2016-06-04 19:32
thomas pts/3 2016-06-04 19:33 (:0)
ただし、すべての端末がutmp(この情報が保存される場所)をサポートしているわけではありません。 Linuxのみに制限されている場合は、いくつかの有用な情報/dev/pts
、つまり所有権情報を持つデバイスを入手できます。
$ ls -l /dev/pts
total 0
crw--w---- 1 tom tty 136, 0 Jun 4 19:34 0
crw--w---- 1 tom tty 136, 1 Jun 4 16:12 1
crw--w---- 1 thomas tty 136, 2 Jun 4 19:33 2
crw--w---- 1 thomas tty 136, 3 Jun 4 19:33 3
crw--w---- 1 tom tty 136, 4 Jun 4 19:34 4
crw--w---- 1 tom tty 136, 5 Jun 4 19:24 5
c--------- 1 root root 5, 2 Jun 4 12:16 ptmx
スクリプトはこれを簡単に確認し、意図したユーザーが誰であるかを判断し、これらの(最終)デバイスに書き込むことができます。
メモ:
「プログラムが出力をブロードキャストする端末をどのように知ることができますか?」に関する一般的なアプローチは、区別する各端末でクライアントを実行してサーバーと通信することです。
プログラムがどのように知っているかを尋ねるコメントがあります。どこ顧客が画面に表示されます。たとえば、window-idで始まり、を使用してウィンドウプロパティを使用してこの情報を取得できます
xwininfo
。端末エミュレータの種類と適切な(または利用可能な)window-idの間に違いがあります。ただし、WINDOWID
各端末の環境変数はこの情報を取得する一般的な方法です(ただし、ブロードキャストを望まない場合はクライアントを介して)。以下は、この方法を使用したサンプル出力です。
xwininfo: ウィンドウ ID: 0x400023 "[!xwininfo] - 平均" 絶対左上隅X:0 絶対左上隅Y:23 相対左上隅X:0 相対左上隅Y:22 幅:486 身長:551 深さ: 24 ビジョン:0x22 ビジュアルグレード:トゥルーカラー ボーダー幅:0 クラス:入出力 カラーマップ:0x21(インストール済み) ビット重力状態: NorthWestGravity ウィンドウ重力状態: NorthWestGravity バックアップストレージの状態:無駄 保存状態:いいえ 地図の状態: IsViewable リダイレクト状態を無視:いいえ コーナーキック: +0+23 -794+23 -794-428 +0-428 -幾何学 80x40+0+1
追加資料: