この簡単なテストコマンドを入力すると:
gnome-terminal -x bash -c "ls;sleep 3"
すぐに戻ることがわかります(もちろん、新しく作成されたターミナルは3秒間残ります)。これは、たとえば、rxvt
(同じコマンドですが、e
を使用)とは対照的です。
ブロッキングの開始が必要な場合、歴史的なコンセンサスは --disable-factory
を使用する であったようです。残念ながら、これはもう機能しません(テスト済みの3.14.2)。
したがって、非同期ではない方法で端末を起動するにはどうすればよいですか?
ボーナス:konsole
、lxterminal
、およびxfce4-terminal
も少なくとも同じ問題を抱えています。それらのコマンド?
私は、terdonの答えといくつかの類似点がある(そして彼の助けを借りて作成された-ありがとう@ terdonこれは!)メソッドを使用しますが、アプローチが少し異なります:
一時ファイルを作成して、子端末が親端末と通信し、対応するbashインスタンスのPIDを通知できるようにします。次に、親端末に一時ファイルを読み取らせてPIDを記憶させ、ファイルを削除して、子端末のbashインスタンスがまだ実行されているかどうかを100ミリ秒ごとに確認します(遅延を変更できます)。そうでない場合、端末は手動で、またはコマンドが終了したために閉じられました。その後、起動コマンドが終了し、親端末が再び使用可能になります。
このアプローチの利点:
起動されるすべてのコマンド(ls; sleep 3
またはそれらの代替)は、実行するafterを担当するコマンド端末のクローズの検出を許可します。そのため、内部コマンドがハングするか、端末が終了する前に手動で閉じた場合、メカニズムはまだ機能しており、無限ループに陥る代わりに外部スクリプトの実行を継続します。
デバッグ出力(子端末ウィンドウを開いた後に「起動」、閉じた後に「終了」)と0.1秒の精度を持つワンライナーとしてのコードは次のとおりです。
pidfile=$(mktemp); gnome-terminal -x bash -c "echo \$$>$pidfile; ls; sleep 3"; until [ -s $pidfile ]; do sleep 0.1; done; terminalpid=$(cat "$pidfile"); rm $pidfile; echo "launched"; while ps -p $terminalpid > /dev/null 2>&1; do sleep 0.1; done; echo "terminated"
またはデバッグ出力なし:
pidfile=$(mktemp); gnome-terminal -x bash -c "echo \$$>$pidfile; ls; sleep 3"; until [ -s $pidfile ]; do sleep 0.1; done; terminalpid=$(cat "$pidfile"); rm $pidfile; while ps -p $terminalpid > /dev/null 2>&1; do sleep 0.1; done
ほぼ同じコードですが、bashスクリプトとして記述された柔軟性があります。
#! /bin/bash
delay=0.1
pidfile=$(mktemp)
gnome-terminal -x bash -c "echo \$$>$pidfile; ls; sleep 3"
until [ -s $pidfile ]
do sleep $delay
done
terminalpid=$(cat "$pidfile")
rm $pidfile
echo "launched"
while ps -p $terminalpid > /dev/null 2>&1
do sleep $delay
done
echo "terminated"
もちろんecho "launched"
行とecho "terminated"
行を省略できます。また、必要に応じてdelay=0.1
行を、端末状態の2つのチェック(秒単位)間の別の遅延に変更できます。多かれ少なかれ正確に。
子端末で別のカスタムコマンドを実行するには、次の行を置き換えます
gnome-terminal -x bash -c "echo \$$>$pidfile; ls; sleep 3"
次のように(大文字のプレースホルダーの代わりにコマンドを挿入してください!)
gnome-terminal -x bash -c "echo \$$>$pidfile; INSERTYOURCOMMANDSHERE"
無限の知恵で、GNOME開発者はそのオプションを削除することにしました。残念ながら、彼らの知恵は、まだリストされているman
ページの更新にも及ばなかった。したがって、gnome-terminal
は常にバックグラウンドで実行され、親のシェルセッションはすぐに返されるように見えます。これを回避するには、いくつかのオプションがあります。
別の端末を使用するだけです。 xterm、rxvt、およびGNOMEターミネーターを試してみましたが、すべて期待どおりに機能しました。
Someいハックを使用します。 gnome-terminal
は、最初の実行時に/usr/lib/gnome-terminal/gnome-terminal-server
を起動します。何らかの理由で、これはプロセスを起動するとすぐに終了することを意味します。説明する:
$ gnome-terminal -x sh -c "ls;sleep 30"
[1] 5896
$ jobs
[1]+ Done gnome-terminal -x sh -c "ls;sleep 30"
上記でわかるように、バックグラウンドで起動した後、起動したジョブはすぐに終了します。つまり、最初にバックグラウンドで起動し、$!
を使用してそれがまだ実行されているかどうかを確認することは最初は考えられません。これは、ファイルを作成するようなエレガントではない何かをする必要があることを意味します。
tmpfile=$(mktemp); gnome-terminal -x sh -c "ls;sleep 30; rm $tmpfile"
while [ -e $tmpfile ] ; do :; done
上記のコマンドは、i)一時ファイル(tmpfile=$(mktemp)
)を作成します。 ii)gnome-terminalを起動し、完了したら$tmpfile
を削除し、iii)一時ファイルが存在する限り何もしない(:
)while [ -e $tmpfile ]
を指示します。これにより、端末はgnome-terminal
によって実行されるプロセスが終了するまで待機してから続行します。
Gnome-terminalパッケージのUbuntuメンテナーはこの問題に気づき、gnome-terminal-3.14.2-0ubuntu3
オプションを再度有効にするラッパースクリプト(Ubuntuパッケージ--disable-factory
)を作成しました。ただし、ラッパースクリプトは機能しません。
gnome-terminal(3.14.2-0ubuntu3)鮮やか; urgency = medium
- debian/gnome-terminal:ラッパースクリプトを追加して、ユーザーが現在無視されている--disable-factoryオプションを渡すと、異なるapp-idでgnome-terminalを起動します。これにより、アップグレードするユーザーの古いランチャーとの互換性が復元されます。 [...]
Ubuntu "Launchpad"をナビゲートすることはできません(オープンソースの場合)。ラッパースクリプトは https://launchpad.net/ubuntu/+archive/primary/+files/gnome-terminal_3にあります.14.2-0ubuntu3.debian.tar.xz (gnome-terminal.wrap
と呼ばれます)。
バグは、gnome-terminal.wrap
スクリプトが間違った子プロセスを待機していることです。ターミナルクライアントではなく、ターミナルサーバーで待機する必要があります。修正方法は、次のように2つのメソッドserver_appeared
およびspawn_terminal_server
を変更することです。
def server_appeared(self, con, name, owner):
# start gnome-terminal now
gt = Gio.Subprocess.new(['/usr/bin/gnome-terminal.real',
'--app-id', name] +
self.args,
Gio.SubprocessFlags.NONE)
# removed a line here: gt.wait_async(...)
def spawn_terminal_server(self, name):
ts = Gio.Subprocess.new(['/usr/lib/gnome-terminal/gnome-terminal-server',
'--app-id',
name],
Gio.SubprocessFlags.NONE)
ts.wait_async(None, self.exit_loop, ts)
修正済みファイルは、次の場所からダウンロードできます。 https://Gist.github.com/ecatmur/00893506a23e828c6688 。
私はパッケージメンテナーに通知しましたので、うまくいけばそれはかなりすぐに修正されるべきです。
別の興味深い事実:gnome-terminalは、gterminal
と呼ばれる代替クライアントを使用して構築できます。このクライアントには、希望どおりの動作をする--wait
オプションがあります。ただし、残念ながらUbuntuはgnome-terminalパッケージにビルドまたはインストールしません。
Google経由でこのサイトにアクセスした2017年2月<t <2018年3月の人々にとって、簡単な解決策は次のとおりです。
gnome-terminal --disable-factory -e "cmd"
gnome-terminalが動作し、期待どおりに同期/ブロック方式で起動します。
以下でテスト:
私は新しいgnome-terminalを使用していますが、gnome-terminalについて説明した動作は、konsole、lxterm、およびrxvtで同じように見えます(3つすべてを試しました)。そのため、OPはこれまでのところ何を望んでいるかを明確にするためのコメントに答えていないので、OPは子端末の終了を待たずに親端末を使い続けたいと考えています。
それはgnome-terminal &
で実現できます。親が終了するときに子端末が閉じられないようにするには、Nohup gnome-terminal &
を使用します。親端末でエラー出力が表示されないようにするには、gnome-terminal 2> /dev/null &
またはNohup gnome-terminal 2> /dev/null &
を使用します。