web-dev-qa-db-ja.com

一部のコマンドが終了するまで端末を「ハング」させるのはなぜですか?

時々、ターミナルからプログラムを実行します、例えば、lxpanel。端末はプロンプトに戻りません。ハングします。押すことができます Ctrl+C プロンプトに戻るには、lxpanelを強制終了します。ただし、 Alt+F2 (コマンドを実行するためのウィンドウをポップアップします)およびlxpanelの実行は正常に動作します。

どうしてこれなの?端末からコマンドを実行することと、を押したときに表示される「実行」ウィンドウからの違い Alt+F2

ここのlxpanelは単に例として使用されました。複数のプログラムでこれを経験しました

23
sqram

デフォルトでは、ターミナルはプログラムをフォアグラウンドで実行するため、プログラムが終了するまでシェルに戻りません。これは、stdinから読み取ったり、stdoutに書き込んだりするプログラムに役立ちます。通常、それらの多くを一度に実行する必要はありません。プログラムをバックグラウンドで実行したい場合は、次のように開始できます。

$ lxpanel &

または、すでに実行されている場合は、 Ctrl+Z 次にbgを実行してバックグラウンドに移動します。いずれにしても、新しいシェルプロンプトが表示されますが、プログラムはまだ実行中であり、その出力はターミナルに表示されます(タイピングの最中に突然表示される可能性があります)

一部のプログラム(通常はデーモン)は、起動時に個別のプロセスをforkし、メインプロセスをすぐに終了させます。これにより、シェルをブロックせずにプログラムを実行し続けることができます

28
Michael Mrozek

端末でプログラムを起動すると、プログラムが停止するまで端末が「ハング」します。押して Ctrl+c プログラムを閉じているため、プロンプトに戻ります。すべてのGUIアプリでこれが表示されます。たとえば、Firefoxを試してください。

Alt + F2などの他の方法を使用したり、メニューをクリックしたりすると、プログラムがバックグラウンドで開始されるため、奇妙なことは何も起こりません(それでもコマンドプロンプトはありません)。

ターミナルからGUIアプリを起動したい場合は、コマンドの最後に&を追加します。

lxpanel &

これは、ターミナルにlxpanelをバックグラウンドで実行し、すぐに別のプロンプトを表示するように指示します。

7
phunehehe

シェルを介して実行されるプログラムは、デフォルトではそのシェルのフォアグラウンドで実行されます。これにより、シェルは操作を一時停止し、端末からプログラムにstdin/stdout/sterrを送信します。デスクトップ環境を介して実行されるプログラムは forked であり、プログラムを実行したプログラムとは無関係に実行されます。これは、コマンドに&を追加することにより、ほとんどのシェルでシミュレートできますが、これでもstd *を端末に接続します(ただし、バックグラウンドプログラムでstdinから読み取ると、さらに複雑になります)。

&バックグラウンドは、後でコンソールとのやり取りを必要とするプログラムを除いて(たとえば、「apt -y update&」は、ユーザーに「本当に本当に強制しますか?」という質問をずっと後に促すため、最終的にSTOP状態になります。 ....誰も見なくなったとき)。

その穴をふさぎ、端末が実際に利用可能になることは決してないことをプロセスに通知するには、コマンドの一部に<&-を追加し、アクティブな端末から完全に切り離して、STDINであることを伝えないようにします。 それを使用する場合は、/ bin/bashがシェルであることを確認してください。スクリプトは、プロンプトをキャストするために使用できる疑似端末がないことに関連するエラーのロギングを続行します。

例えば:

`./runme.sh &> runme.log <&- & disown`

は、現在のターミナルセッションとの関連付けを解除するための私の究極の方法です。 STDOUTとSTDERRの両方がrunme.logに記録されます。コンソールまたはシェルがすぐに終了するか、別のアカウントにログアウト/ suするか(runmeからのターミナルガベージがない)かどうかは関係ありません。 PID関係が削除されます。

更新:それでも、セマフォを元の親の名前に関連付けるのに問題があったので、代わりに次のようにお勧めします。

at now <<< "(cmd1; cmd2; etc.) &> logfile.log"

もちろん、CRONからの出力を電子メールで送信する場合は&>を削除するか、ファイルではなくすべて/ dev/nullにリダイレクトします。

2
Marcos