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


22

時々、ターミナルからプログラムを実行しますlxpanel。ターミナルはプロンプトに戻りません。ハングします。Ctrl+ Cを押してプロンプトに戻ることができますが、それはを殺しlxpanelます。ただし、Alt+ F2(コマンドを実行するためのウィンドウが表示されます)を押して実行lxpanelすると、正常に機能します。

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

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


1
ヒント:GNU Screen(screen)は、とりわけ、実行時間の長いプロセスを「ラップ」するために使用できます。そこから切り離してシェルに戻り、再接続して実行中のプロセスからの出力を確認できます。再接続は、別の端末、SSHなどから行うこともできます。この種のことを可能にする他のプログラムもあります。
poplitea

回答:


28

デフォルトでは、端末はプログラムをフォアグラウンドで実行するため、プログラムが終了するまでシェルに戻りません。これは、stdinからの読み取りおよび/またはstdoutへの書き込みを行うプログラムに役立ちます。通常、それらの多くを一度に実行することは望ましくありません。プログラムをバックグラウンドで実行する場合は、次のように起動できます。

$ lxpanel &

または、既に実行されている場合は、Ctrl+で一時停止してZから実行bgして、バックグラウンドに移動できます。いずれにしても、新しいシェルプロンプトが表示されますが、プログラムはまだ実行中であり、その出力はターミナルに表示されます(したがって、入力中に突然表示されることがあります)

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


では、Alt + f2を押して「実行」ウィンドウからプログラムを実行すると、システムは実際に何をしますか?(少なくともgnomeとopenboxでは、alt + f2がそれを行います)。コマンドを入力するとすぐにプログラムが起動し、ボックスが消えてしまうためです。&を追加するだけですか?
sqram

2
@lyrae:デフォルトでは、シェルはプログラムの完了を待ってからシェルセッションを続行します。「ハング」の定義により、「ハング」しません。alt + f2はプログラムを待機しません。シェルがプログラムの完了を待機する理由は、シェルがユーザーがシェルに入力したものをプログラムの標準入力および/または表示プログラムの標準出力にリダイレクトできるためです。alt + f2は主にGUIプログラムの起動に使用されるため、alt + f2は標準入出力を使用する可能性を提供しないため、待機する必要はありません。
ライライアン

1
@lyrae:alt + f2は、プログラムをバックグラウンドで起動するために特別なことはしません。何か特別なことをしているのはシェルで、「&」を追加することがシェルの機能です。「&」なしでコマンド開始すると、シェルはプログラムの標準入力を独自の標準入力にリダイレクトし、プログラムの標準出力を独自の標準出力にリダイレクトします(シェルは、Ctrl -C、SIGINTシグナルコマンドをフォアグラウンドプログラムに送信します)。'&'は、シェルにそれらを行わずにプログラムを開始するように指示します(これも不自然です)。
ライライアン

1
@LieRyanシェルが言っていることの一部は、実際にはカーネルのターミナルドライバーによって処理されます。シェルがwait()を呼び出すこと以外は、「with&」は一般的に「&なし」よりも「特別」です。 alt-f2では行われません。
Random832

6

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

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

それでもターミナルからGUIアプリを起動する場合&は、コマンドの最後に次のように追加します。

lxpanel &

これにより、端末lxpanelはバックグラウンドで実行され、すぐに別のプロンプトが表示されます。


3

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


2

&バックグラウンドは、後でコンソールとの対話を必要とするプログラムを除いて十分です(たとえば、「apt -y update&」は、ユーザーに「本当に本当に強制する?」 ....誰も見ていないとき)。

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

例えば:

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

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

更新:それでも、セマフォが元の親の名前に関連付けられているので問題がありましたので、今では代わりに推奨します:

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

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


私が使用し始めたものを達成するためのやや複雑な方法は、at now <<< "(cmd1; cmd2; etc.) &> logfile.log"
マルコス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.