UKey's Labo

linux – ジョブのバックグラウンド実行

以下手順で行います。

  1. プロセスを実行
  2. ctrl + zで中断する。
  3. bgコマンドでプロセスをバックグラウンドに移す。
# sleepで実験
sleep 10

# ctrl + zで中断
^Z
[1]+  Stopped                 sleep 10

# jobを確認
jobs
[1]+  Stopped                 sleep 10

# bgコマンドでjobをバックグラウンド実行
# bg [job ID]
bg 1
[1]+ sleep 10 &

# 実行終了すると、以下が出力される
[1]+  Done                    sleep 10

コンソール出力のあるプロセスのバックグラウンド実行

pingなど、コンソールに実行結果が帰ってくるプロセスだと、バックグラウンドで実行していても、コンソールに結果が出力されるため、うまくいかない。

そのため、コンソールの出力を捨てる必要がある。

# pingで実験してみる
ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=2.50 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=4.76 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=1.46 ms
64 bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=1.51 ms

# ctrl + zで中断
^Z
[1]+  Stopped                 ping 192.168.1.1

# バックグラウンド実行
bg 1
[1]+ ping 192.168.1.1 &

# コンソールに結果が出力されて、まともにコマンドも打ちにくくなる
[email protected]:~ $ 64 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=2.04 ms
64 bytes from 192.168.1.1: icmp_seq=6 ttl=64 time=1.79 ms
64 bytes from 192.168.1.1: icmp_seq=7 ttl=64 time=1.47 ms
64 bytes from 192.168.1.1: icmp_seq=8 ttl=64 time=1.38 ms
64 bytes from 192.168.1.1: icmp_seq=9 ttl=64 time=1.46 ms
64 bytes from 192.168.1.1: icmp_seq=10 ttl=64 time=3.85 ms
64 bytes from 192.168.1.1: icmp_seq=11 ttl=64 time=2.66 ms

ちなみに、この状態でpingを止めようとして、ctrl + cを実行しても、止まりません。コンソールに出力され続けていますが、pingがバックグラウンドで実行されているためです。この場合、pingをフォアグラウンドに戻す必要があります。フォアグラウンドに戻す場合、fgコマンドで行います。

# pingを実行
ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=1.50 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=1.50 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=1.54 ms
# ctrl + z で中断
^Z
[1]+  Stopped                 ping 192.168.1.1
# bgコマンドでバックグラウンド実行
[email protected]:~ $ bg 1
[1]+ ping 192.168.1.1 &
# バックグラウンド実行ではあるが、コンソールに結果が出力される
[email protected]:~ $ 64 bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=1.61 ms
64 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=1.49 ms
64 bytes from 192.168.1.1: icmp_seq=6 ttl=64 time=1.43 ms
64 bytes from 192.168.1.1: icmp_seq=7 ttl=64 time=1.58 ms
64 bytes from 192.168.1.1: icmp_seq=8 ttl=64 time=1.50 ms

# fgコマンドでpingをフォアグラウンドにする
fg 1

# pingがフォアグラウンドで実行される
ping 192.168.1.1
64 bytes from 192.168.1.1: icmp_seq=10 ttl=64 time=1.75 ms
64 bytes from 192.168.1.1: icmp_seq=11 ttl=64 time=1.49 ms
64 bytes from 192.168.1.1: icmp_seq=12 ttl=64 time=2.68 ms
# ctrl + c で終了させる
^C
--- 192.168.1.1 ping statistics ---
12 packets transmitted, 12 received, 0% packet loss, time 15380ms
rtt min/avg/max/mdev = 1.430/1.629/2.687/0.332 ms

こういう場合は、バックグラウンド時に結果をコンソールに出力されないよう、/dev/nullに出力結果をリダイレクトします。

# pingを/dev/nullにリダイレクト
ping 192.168.1.1 > /dev/null

# ctrl + zで中断
^Z
[1]+  Stopped                 ping 192.168.1.1 > /dev/null

# バックグラウンド実行
bg 1
[1]+ ping 192.168.1.1 > /dev/null &

# jobを確認
jobs
[1]+  Running                 ping 192.168.1.1 > /dev/null &

結果を捨てないように、リダイレクトでファイルに出力する場合も、上記と同様にコンソールに結果は出力されないようになります。適宜使い分けます。

pingでは実用性なさそうですが、参考までに。

プロセスの起動確認

一旦コンソールからログアウトしてしまうと、jobsコマンドでバックグラウンドで実行中のコマンドが確認できなくなります。その場合は、psコマンドでプロセスを確認します。引数auxを使う場合は、grepなどで絞り込むほうが目的のものも見つけやすくなります。

ps aux | grep ping
user 14932  0.0  0.0   4928   680 pts/0    S    18:10   0:00 ping 192.168.1.1

psの引数 * a – 自分以外のユーザ全てのプロセスを表示 * u – ユーザ名と開始時間を表示 * x – デーモンを表示

バックグラウンドにすると動かなくなるjob

バックグラウンド実行するとjobがStoppedのままで、フォアグラウンドに戻すとRunningになるようなjobは、入力待ちになってしまっている可能性があります。

その場合、標準入力に/dev/nullを与えてあげる必要があります。

仮に、そのようなjobをsample.shとすると、以下のように実行し、その後バックグラウンド実行にします。

# 標準入力に/dev/nullを与えて実行
bash sample.sh </dev/null

# 中断する
ctrl + z

# バックグラウンド実行する
bg

参考サイト