私はLinuxを学んでいます。プロセスを端末に貼り付けることができるというアイデアが浮上しました。端末(TTY)にプロセスを接続することはどういう意味ですか?なぜこれを行うべきですか?
答え1
メモ: Unixの仕事のコントロールをよりよく理解するために、このトピックのウィキペディアページに案内します。ジョブ制御(Unix)。
追加端末?
「ターミナルに接続する」というフレーズは、通常、シェルのコンテキストでタスクについて話すときに聞くことです。しかし、それは他の意味も持っています。 「ターミナルへのプロセスの接続」という語句は、gdb
特定のプロセスID(PID)に接続し、情報を一覧表示または監視するなどのstrace
ツールを使用することを意味します。lsof
これらの両方について議論する予定ですが、まず作業キューについて議論します。なぜなら、それがあなたが探しているキューだと思うからです。
背景 - ジョブキュー
Unixファミリーのオペレーティングシステムでは、一般にタスクという概念を見ることができます。通常、私が使用したほとんどのUnixファミリーオペレーティングシステムでも同様の方法で動作します。つまり、バックグラウンドで実行でき、キュー(ジョブキュー)に番号を割り当てることができ、そのジョブキュー内の番号のコンテキストに従って操作できます。
ジョブキューに何かを入れるために、この動作をバックグラウンド処理と呼びます。すでにバックグラウンドで実行されているジョブを再開している場合は、これをフォアグラウンド処理と呼びます。これを行う一般的なコマンドbg
はですfg
。&
実行するコマンドの最後に「&」記号を使用して、ジョブをバックグラウンドに即座に切り替えることもできます。
はい
働く
$ sleep 2 &
[1] 19189
ここでは、sleepコマンドを2秒間実行し、バックグラウンドに入れました。出力は、ジョブキュー番号([1]
)やバックグラウンドジョブのプロセスID 19189などの便利な情報をすぐに提供します。
これが最終的に終了すると、実行中の端末に次のメッセージが表示されます。
$
[1]+ Done sleep 2
前景と背景
バックグラウンドジョブに対してアクションを実行するには、次のようにします。
$ sleep 20 &
[1] 19207
$ fg
sleep 20
^C
ここでは、ジョブをバックグラウンド(&
)に送信してからフォアグラウンド()に戻し、fg
+ Ctrl(C)^C
コマンドを使用してジョブを終了します。
バックグラウンドタスクが複数ある場合:
$ sleep 20 &
[1] 19224
$ sleep 20 &
[2] 19225
$ sleep 20 &
[3] 19226
$ jobs
[1] Running sleep 20 &
[2]- Running sleep 20 &
[3]+ Running sleep 20 &
私たちはコマンドを使ってそれらを見ることができますjobs
。 #3と#2の横にある小さな合計を確認してください+
。ジョブキュー番号を指定せずにコマンドを-
実行すると、fg
最後のジョブがジョブキュー()に追加されます+
。たとえば、
$ fg
sleep 20
^C
$ jobs
[1]- Running sleep 20 &
[2]+ Running sleep 20 &
殺す
ジョブキュー番号を使用してジョブを処理できます。一つの方法はそれらを殺すことです。ジョブキュー番号を参照するには%
他のコマンドと一緒に参照する場合は、その番号の前にプレフィックスを付けることができますkill
。もちろん、kill
一度に複数を使用することも、1つだけを使用することもできます。
$ kill %3 %4 %5
$ jobs
[3] Terminated sleep 20
[4] Terminated sleep 20
[5]- Terminated sleep 20
[6]+ Running sleep 20 &
PIDに接続された背景
プロセスを端末に接続することは、次のことを意味することもあります。これは私のシェルのPIDです。
$ echo $$
23543
他のシェルでは、strace
プロセスを実行して接続して、どのシステムコールが実行されているかを確認します。
$ strace -p 23543
strace: Process 23543 attached
read(0,
メモ:read
ここでforコマンドを待っていることがわかります。これがターミナル/シェルの用途です。
ここでコマンドを入力し始め、ls
シェルがこれをシステムコールの形でシェルにエコーするのを見ることができますwrite()
。
read(0, "l", 1) = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "l", 1) = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(0, "s", 1) = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "s", 1) = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(0,
これは、端末にプロセスを接続する別の形式です。
その他の形態
プロセスを端末に接続するためのより曖昧な参照の1つをここでも仮定できます。このU&L Q&Aの質問は次のとおりです。分離したプロセスに端末を接続するには?このコンテンツのすべての形式が含まれています。
この形式の引用の基本的な前提は、バックグラウンドタスクを完了し、現在のシェルでそのタスクを「切断」したことです。または、コマンドを使用してnohup
これを実行できますdisown
。
プロセスが拒否された場合、これ以上jobs
コマンドfg
をbg
使用して操作を実行することはできません。現在、シェルのPIDに関連付けられていません。
reptyr
以前に拒否されたプロセスを再取得する従来の方法は、PIDを既存のシェルに再接続するなどのツールを使用することです。たとえば、私たちが2つの仕事を始め、それが次のようになったとしましょうnohup
。
$ nohup sleep 200 &
[1] 19720
$ nohup sleep 200 &
[2] 19721
それでも端末のジョブキューに接続されていますdisown
。次のようにしましょう。
$ jobs
[1]- Running nohup sleep 200 &
[2]+ Running nohup sleep 200 &
$ disown -a
今彼らは消えました:
$ jobs
$
これらはまだ元のシェルPID(23543)の子としてリストされています。
$ ps -eaf|grep -E "19720|19721"
vagrant 19720 23543 0 18:29 pts/1 00:00:00 sleep 200
vagrant 19721 23543 0 18:29 pts/1 00:00:00 sleep 200
ログアウトしてから再度ログインすると、これらのプロセスがデフォルトのPID 1の親としてリストされていることがわかります。
$ ps -eaf|grep -E "19720|19721"
vagrant 19720 1 0 18:29 ? 00:00:00 sleep 200
vagrant 19721 1 0 18:29 ? 00:00:00 sleep 200
nohup
これらのプロセスは、私たちが編集して編集するので、これを行うことができますdisown
。そのうちの1つを再接続してみましょう。
$ reptyr -s 19720
[-] Timed out waiting for child stop.
^C
メモ:上記では、PID 19720をシェルに再接続してからCtrl+で終了しますC。今は消えたことがわかります。
$ ps -eaf|grep -E "19720|19721"
vagrant 19721 1 0 18:29 ? 00:00:00 sleep 200