1. inosy22

    Posted

    inosy22
Changes in title
+Linuxコマンド(Bash)でバックグラウンド実行する方法のまとめメモ
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,282 @@
+bashコマンドのバックグランド実行方法について、まとまっている記事が見つからなかったのでまとめメモ
+# 通常のバックグラウンド実行
+
+## &でバックグランド実行
+参考:http://kazmax.zpp.jp/linux_beginner/process_background.html
+
+もっとも基本的なバックグランド実行、コマンドの後ろに&をつけて実行する。
+ターミナルの切断が切れたりしてログアウトした場合に、
+この方法で実行したプロセスはkillされてしまうので注意する。
+途切れたら困る処理の場合はtmuxのセッション上で実行、
+もしくは後述するnohupコマンドでのバックグラウンド実行推奨。
+
+
+```Bash
+# バックグラウンド実行
+$ sleep 5 &
+[1] 21871
+
+# プロセス確認
+$ ps $! # ps 21871
+ PID TTY STAT TIME COMMAND
+21871 pts/0 S 0:00 sleep 5
+```
+
+
+## &で連続したコマンド群をバックグランド実行
+複数コマンドを順番に実行する処理をバックグランド実行したい場合
+例えば、5秒たったら、「done」という出力を得るコマンド
+
+```Bash
+# フォアグラウンド実行
+$ sleep 5; echo done
+```
+
+これをバックグランドで実行する方法たち
+
+1.シンプルにコマンドをカッコでくくる
+
+```Bash
+$ (sleep 5; echo done) &
+
+# ※以下のようにすると`sleep 5`がバックグラウンド実行されないためダメ
+# $ sleep 5; echo done &
+```
+
+2.コマンドを中かっこでくくる
+
+```Bash
+# 前後のスペースとコマンド群の最後のセミコロン必要なの注意
+$ { sleep 5; echo done; } &
+```
+
+3.複数行に分けてコマンドを中かっこでくくる
+
+```Bash
+$ {
+> sleep 5
+> echo done
+> } &
+```
+
+4.shコマンドを非同期実行する
+shコマンドの-cオプションでコマンドをひとまとめにして、
+shコマンド自体を非同期実行とする
+
+```
+$ sh -c 'sleep5; echo done' &
+```
+
+5.そもそもシェルにする
+
+```Bash:test.sh
+#!/bin/sh
+sleep 5
+echo done
+```
+
+```Bash
+$ sh test.sh &
+```
+
+#nohupでログアウトしてもバックグラウンド実行
+## nohupでsshログアウトしても実行維持
+nohupコマンドでsshログアウト時に送られるHUPシグナルによる
+バックグラウンドジョブのkillを行われないようにする
+
+HUPシグナルについては以下の資料がとても参考になる
+参考:http://qiita.com/yushin/items/732043ee23281f19f983
+
+```Bash
+$ nohup sleep 5 &
+```
+標準出力などがある場合はデフォルトで`./nohup.out`というファイルに出力される。
+以下のようにファイルを指定すれば、任意のファイルに出力できる。
+
+```Bash
+$ nohup echo test > test.txt &
+```
+
+## nohupで連続したコマンド群をバックグランド実行
+nohupはかっこでくくる系でまとめて実行することはできないので、
+shコマンドでまとめて実行する
+
+```Bash
+# コマンド上で実行の場合
+$ nohup sh -c 'sleep 5; echo done' &
+
+# 先ほどのシェルスクリプトで実行の場合
+$ nohup sh test.sh &
+```
+
+# 実行中のジョブをバックグラウンドへ
+##
+参考:http://kazmax.zpp.jp/linux_beginner/jobs_fg_bg.html
+
+こんなコマンドでフォアグラウンド実行してしまったとする。
+
+```Bash
+$ sleep 100
+```
+これをバックグラウンド実行するときは、
+まず、`control+z`で実行中のJobを停止
+
+```Bash
+# 実行後、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コマンドを利用する
+
+```Bash
+# 先ほどの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コマンドを使うとプロセスの終了をキャッチすることができる。
+
+```Bash
+$ wait ${プロセスID}
+# 複数の場合は空白区切りでプロセスIDを並べる
+# プロセスIDを指定しない場合は、起動したすべてのバックグランドジョブを待つ
+```
+
+これを利用すると複数のバックグラウンド実行が終了した後の処理を記述できる。
+
+## 以前に実行したすべてのバックグランドジョブの同期待ち
+
+```Bash:sync.sh
+#!/bin/sh
+# 一つ目のジョブ
+{
+ sleep 10
+ echo done1
+} &
+
+# 2つめのジョブ
+{
+ sleep 5
+ echo done2
+} &
+
+# 終了待ち
+wait
+echo done3
+```
+実行すると以下のようになって、期待通りの動作をしていることがわかる。
+
+```Bash
+$ sh sync.sh
+done2
+done1
+done3
+```
+
+## 一部のジョブの同期待ち
+プロセスIDを指定してwaitすれば、特定のプロセスのみを同期することができるので、プロセスIDを添え字に使った配列を利用すると簡単
+
+```Bash: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
+```
+
+実行結果は期待通り
+
+```Bash
+$ sh part_sync.sh
+done3
+done1
+done4
+$ done2
+```
+
+# 検証環境
+検証した環境
+
+```Bash
+$ 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.
+```