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

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

lxpanel時々†などのプログラムを端末で実行します。端末はプロンプトに戻らずに停止します。Ctrl+を押してCプロンプトに戻ることができますが、これは終了しますlxpanel。しかしAlt、+を押してF2(コマンドを実行するウィンドウが表示されます)、実行するとlxpanel問題はありません。

なぜこれですか?端末でコマンドを実行するのとAlt+を押すと表示される実行ウィンドウでコマンドを実行するのはどう違いますかF2

ここのlxpanelは単なる例です。いくつかのプログラムでこれをしました。

答え1

デフォルトでは、ターミナルはプログラムをフォアグラウンドで実行するため、プログラムが完了するまでシェルに戻りません。これは、標準入力から読み込んだり、標準出力に書き込むプログラムに便利です。通常、多くのプログラムが同時に実行されることを望まない。プログラムをバックグラウンドで実行するには、次のように起動できます。

$ lxpanel &

または、すでに実行している場合はCtrl+を使用してZ一時停止し、実行してbgバックグラウンドに移動することもできます。どちらも新しいシェルプロンプトが表示されますが、プログラムはまだ実行中であり、その出力は端末に表示されます(したがって、入力中にポップアップが表示されることがあります)。

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

答え2

ターミナルでプログラムを起動すると、プログラムが停止するまでターミナルは「停止します」。Ctrl+を押すとcプログラムが閉じ、プロンプトに戻ります。すべてのGUIアプリケーションでこれを見ることができます。たとえば、Firefoxを試してみてください。

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

それでも端末でGUIアプリケーションを起動するには、&以下のようにコマンドの最後に追加します。

lxpanel &

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

答え3

デフォルトでは、プログラムはそのシェルの前景で実行されるシェルを介して実行されます。これにより、シェルは操作を中断し、stdin/stdout/sterr を端末からプログラムに渡します。デスクトップ環境で実行されるプログラムは、二股に分かれた、それを実行するプログラムとは独立して実行するようにします。これは&コマンドにaを追加することでほとんどのシェルでシミュレートできます。しかし、これはまだstd *がターミナルに接続することを意味します(デーモンのstdinで読むのはより複雑ですが)。

答え4

&背景は大丈夫です。後でコンソールインタラクションが必要なプログラムを除いては問題ありません(たとえば、「apt -y update&」は、はるかに後でユーザーに「本当に強制しますか?」という質問を表示するため、停止したままになります)。 .これ以上誰も見ていないとき)。

この穴を塞いで端末が実際に使用できなくなることをプロセスに知らせるために、コマンドに<&-を追加してコマンドをアクティブな端末から完全に切り離し、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にリダイレクトしてください。

関連情報