Help us understand the problem. What is going on with this article?

Linuxコマンド(Bash)でバックグラウンド実行する方法のまとめメモ

More than 3 years have passed since last update.

bashコマンドのバックグランド実行方法について、まとまっている記事が見つからなかったのでまとめメモ

通常のバックグラウンド実行

&でバックグランド実行

参考:http://kazmax.zpp.jp/linux_beginner/process_background.html

もっとも基本的なバックグランド実行、コマンドの後ろに&をつけて実行する。
ターミナルの切断が切れたりしてログアウトした場合に、
この方法で実行したプロセスはkillされてしまうので注意する。
途切れたら困る処理の場合はtmuxのセッション上で実行、
もしくは後述するnohupコマンドでのバックグラウンド実行推奨。

# バックグラウンド実行
$ sleep 5 &
[1] 21871

# プロセス確認
$ ps $! # ps 21871
  PID TTY      STAT   TIME COMMAND
21871 pts/0    S      0:00 sleep 5

&で連続したコマンド群をバックグランド実行

複数コマンドを順番に実行する処理をバックグランド実行したい場合
例えば、5秒たったら、「done」という出力を得るコマンド

# フォアグラウンド実行
$ sleep 5; echo done

これをバックグランドで実行する方法たち

1.シンプルにコマンドをカッコでくくる

$ (sleep 5; echo done) &

# ※以下のようにすると`sleep 5`がバックグラウンド実行されないためダメ
# $ sleep 5; echo done &

2.コマンドを中かっこでくくる

# 前後のスペースとコマンド群の最後のセミコロン必要なの注意
$ { sleep 5; echo done; } & 

3.複数行に分けてコマンドを中かっこでくくる

$ {
> sleep 5
> echo done
> } &

4.shコマンドを非同期実行する
shコマンドの-cオプションでコマンドをひとまとめにして、
shコマンド自体を非同期実行とする

$ sh -c 'sleep5; echo done' &

5.そもそもシェルにする

test.sh
#!/bin/sh
sleep 5
echo done
$ sh test.sh &

nohupでログアウトしてもバックグラウンド実行

nohupでsshログアウトしても実行維持

nohupコマンドでsshログアウト時に送られるHUPシグナルによる
バックグラウンドジョブのkillを行われないようにする

HUPシグナルについては以下の資料がとても参考になる
参考:http://qiita.com/yushin/items/732043ee23281f19f983

$ nohup sleep 5 &

標準出力などがある場合はデフォルトで./nohup.outというファイルに出力される。
以下のようにファイルを指定すれば、任意のファイルに出力できる。

$ nohup echo test > test.txt &

nohupで連続したコマンド群をバックグランド実行

nohupはかっこでくくる系でまとめて実行することはできないので、
shコマンドでまとめて実行する

# コマンド上で実行の場合
$ nohup sh -c 'sleep 5; echo done' &

# 先ほどのシェルスクリプトで実行の場合
$ nohup sh test.sh &

実行中のジョブをバックグラウンドへ

参考:http://kazmax.zpp.jp/linux_beginner/jobs_fg_bg.html

こんなコマンドでフォアグラウンド実行してしまったとする。

$ sleep 100

これをバックグラウンド実行するときは、
まず、control+zで実行中のJobを停止

# 実行後、Control+zで停止
$ sleep 100
^Z
[1]+  停止                  sleep 100

# jobsコマンドで後ほど確認もできる
$ jobs
[1]+  停止                  sleep 100

--------------------------------------

# ジョブが複数あった場合はこんな感じになる
$ jobs
[1]   停止                  sleep 100
[2]-  停止                  sleep 90
[3]+  停止                  sleep 80
# []の中身がジョブ番号
# + : カレントジョブ
# - : 前のジョブ

# 停止しているジョブをバックグラウンド実行
# (ジョブ番号を指定しなければ、カレントジョブとなる)
$ bg ${ジョブ番号}

この方法だと通常のバックグラウンド実行と同じで、
ログアウトしてしまうとプロセスがkillされてしまう

実行中のジョブをログアウト時もバックグラウンド実行する

disownコマンドを利用する

# 先ほどのjobの1番を実行
$ bg 1

# 実行状態になっていることを確認
$ jobs
[1]   実行中               sleep 100 &
[2]-  停止                  sleep 90
[3]+  停止                  sleep 80

# disown %${job番号} で自分のjobテーブルから外れて実行される
$ disown %1

# jobsから消える
$ jobs
[2]-  停止                  sleep 90
[3]+  停止                  sleep 80

# プロセスを見ると動作している
$ ps x | grep sleep | grep -v grep
22222 pts/3    S      0:00 sleep 100
22223 pts/3    T      0:00 sleep 90
22224 pts/3    T      0:00 sleep 80

※ジョブが停止中の状態でdisownしてしまうと、
ジョブテーブルから除外され、ログアウトしても消えないプロセスが残ってしまうので、手動でkillすること

シェルスクリプト内でのバックグランド実行と同期待ち

waitコマンドを使うとプロセスの終了をキャッチすることができる。

$ wait ${プロセスID}
# 複数の場合は空白区切りでプロセスIDを並べる
# プロセスIDを指定しない場合は、起動したすべてのバックグランドジョブを待つ

これを利用すると複数のバックグラウンド実行が終了した後の処理を記述できる。

以前に実行したすべてのバックグランドジョブの同期待ち

sync.sh
#!/bin/sh
# 一つ目のジョブ
{
  sleep 10
  echo done1
} &

# 2つめのジョブ
{
  sleep 5
  echo done2
} &

# 終了待ち
wait
echo done3

実行すると以下のようになって、期待通りの動作をしていることがわかる。

$ sh sync.sh
done2
done1
done3

一部のジョブの同期待ち

プロセスIDを指定してwaitすれば、特定のプロセスのみを同期することができるので、プロセスIDを添え字に使った配列を利用すると簡単

part_sync.sh
#!/bin/sh

# プロセスIDの配列
pids=()

# 一つ目のジョブ (同期する)
{
  sleep 10
  echo done1
} &
# 直前のpidを格納
pids[$!]=$!

# 2つめのジョブ (同期しない)
{
  sleep 20
  echo done2
} &

# 3つめのジョブ (同期する)
{
  sleep 5
  echo done3
} &
# 直前のpidを格納
pids[$!]=$!

# 終了待ち
wait ${pids[@]}
echo done4

実行結果は期待通り

$ sh part_sync.sh
done3
done1
done4
$ done2

検証環境

検証した環境

$ cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)

$ bash --version
GNU bash, バージョン 4.2.46(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
ライセンス GPLv3+: GNU GPL バージョン 3 またはそれ以降 <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
inosy22
仕事でWebエンジニア、趣味でゲームクリエイター 設計周りの話が好きです 現在: Golang/Vue.js(Nuxt.js)/C#(Unity) 過去: PHP/Java/C++/React
http://the-last-dinner.club
gamewith
GameWithは、ゲームをプレイされる皆様がより深くゲームを楽しんで頂ける環境を提供するべく設立されました。あなたがゲームをする時のお供になる。これが私達の目標です。
https://gamewith.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした