【メモ】Ubuntu環境で知っておきたいバックグラウンドプロセス管理入門

普段の開発では、ローカル環境でプログラムを実行することが多いのですが、長時間の実行が必要な機械学習の学習処理やバッチ処理などでは、ターミナルを閉じてもプログラムの実行を止めずに継続して実行する必要性に迫られることがあります。

Xな環境であれば複数のターミナルを開いて管理することも可能ですが、画面が占有されてしまう問題があります。そこで、前々から気になっていたターミナルを閉じてもプログラムを実行させる方法について少し調べてみることにしました。

実行継続の方法と、これまで特に使う意識をしていなかったscreentmuxについてもまとめてみます。

ターミナル上のプログラムの実行を継続する4つの方法

UbuntuなどLinux関連のターミナル上のプログラムの実行を継続する方法として、主に以下の4つがあるでしょうか?

1. &を使用する方法

シェルなどを学ぶときの一般的な形ですよね。コマンドの末尾に&を付けることで、バックグラウンドでプログラムを実行できます。

$ 【プログラム名】 &

標準出力がある場合が面倒なので少し注意がいると思います。この場合はターミナルを閉じてしまうとプログラムが終了します。あくまでもシェルの入力を止めない手段と考えたほうがいいのでしょうね。

例えばpingコマンドを以下のように実行すると

$ ping localhost &

ターミナルのプロンプトがpingコマンドの出力結果によって入力が困難な状態になります。表示を気にせず入力できますが、生産性は大きく損なわれます。終了させるにはkill %%などを実行すればOKです。

2. nohupを使用する方法

端末の切断に影響されずに後続に指定したコマンドせずに実行するnohupです。

起動するプログラムの前にnohupといれてプログラムを起動する方法です。末尾に&をいれることでプロンプトの入力が可能になります。逆に入れないとプロンプトの入力ができなくなるので注意。

この方法は、特にサーバー上で長時間実行するプロセスや、SSHセッションが切断される可能性がある環境での実行に非常に有用です。例えば、大規模なデータ処理やバックアップ処理などを実行する際によく使用します。

私の場合は、昔はテープバックアップでよくお世話になりました。

使用方法

$ nohup 【プログラム名】 &

nohupの動き

nohupは、HUP(ハングアップ)シグナルを無視してコマンドを実行するためのツールです。一般にHUPシグナルは、通常ユーザーが端末セッションを終了したときに発生し、実行中のプロセスを終了させる原因となります。

プログラムの標準出力はどうなる?

nohup時のプログラムは標準出力が以下のように制御されます。

  • 基本的にカレントディレクトリの'nohup.out'ファイルに出力を追記します。(起動時にそのように表示されます)
  • できない場合は、ホームディレクトリの'$HOME/nohup.out'に出力を追記します。

ちなみに、標準エラー出力は標準出力にリダイレクトされます。

例えばpingコマンドを以下のように実行すると

$ nohup ping localhost &

バックグラウンドでプロセスが実行され、標準出力はファイルに格納されます。プロンプトも表示する 無限ループのプロセスを終了させるにはkillコマンドなど使用するなどを行います。

欠点

1ユーザがnohupで複数のプロセスを実行した場合、全ての出力が同じnohup.outファイルに追記されていきます。

  • 複数プロセスの出力が時系列順に混ざって記録される
  • どのプロセスの出力かの区別が困難になる可能性がある

リダイレクトでファイル指定をすることで回避できます。

$ nohup プログラム1 > output1.log 2>&1 &
$ nohup プログラム2 > output2.log 2>&1 &

さらなる注意点

標準エラー出力stderrも同様に混在することを忘れないようにしましょう。 また、ファイルサイズが予想以上に大きくなる点も注意したほうがいいですね。

実運用では各プロセス毎に個別にリダイレクト先を指定することを推奨します。

3. screen/tmuxを使用する方法

nohupを使うと、ターミナルを閉じても実行が継続されますが、プロセスの状態確認やログが少し面倒です。 そこで登場するのがscreentmuxというターミナルマルチプレクサ(複数の仮想端末を管理するツール)となります。

ターミナルマルチプレクサには以下の機能があります。

  • SSH接続が切れても作業を継続可能
  • 1つの端末で複数のセッションを管理
  • セッションのデタッチ/アタッチが可能
  • 画面分割機能

ターミナルマルチプレクサ screentmux

screenについて

screenは古くからある定番ツールで、以下のような操作を行います。 screen経由でプログラムを実行すると一般の実行と同じように実行できますが、表示を切り替えることができる点がnohupと違う点ですね。

# 新規セッション開始
$ screen  【プログラム名】
#### 【Ctrl+A, D】 # デタッチ
#### 【Ctrl+D】 # 強制終了
#### 【Ctrl+A, K】 # 確認あり終了
# セッション一覧
$ screen -ls
# 再接続
$ screen -r [ID]  

※最近のディストリビューションには代替ツールであるtmuxがリリースしたことで、デフォルトパッケージから除外するようになったようです。

念のためインストール方法

$ sudo apt update
$ sudo apt install screen

tmux

一方、tmuxはより新しく・より多機能なツールです。

# 基本的な使い方
$ tmux # 新規セッション開始
#### 【Ctrl+B, D】 # デタッチ
#### 【Ctrl+D】 # 終了
#### 【Ctrl+B, S】 # セッションの切り替え(メニュー形式)
$ tmux ls # セッション一覧
$ tmux attach # 再接続

プロセスというよりもターミナルを増やす感覚でscreenと同様なことができるようです。配置や分割のカスタマイズ性も高いのが特徴のようです。

screentmuxの使い分け

今回この2つを初めて使ってみましたが結構使いやすいかも。screenはプロセス単位、tmuxターミナル単位に近い印象がありました。結構ターミナルのタブを増やして作業を行うことが多かったのですが、これらを使用することでWindowsのタスクバーに並ぶターミナル数を減らすことが出来る点がいいですね。

4. systemdのサービスとして登録

リリースされたアプリの場合にはサービス化を行うといいでしょう。さすがにメモでは書ききれないので省略します😑

実際の使い分け

個人的な感想としては

  • 短期的な実行管理にはnohup
  • 開発作業中の実行管理にはtmux
  • 長期的な運用にはsystemd

となるでしょうか。

おわりに

これまではnohupで済ませていた時期もありましたが、tmuxを使うようになってからは複数のプロセスを効率的に管理でき、作業効率が向上しました。学び直しも重要ですね😊