Linuxで処理をバックグラウンドに切り替えて安全にログアウトする方法(bgコマンドなど)

はやし
2023-06-07
2023-06-09

thum_oss

はじめに

サーバエンジニアをやっていたらこんな経験はないでしょうか?

  • フォアグラウンドで処理を実行したけど、想定より時間がかかって終わらない
  • 別の予定があるので、それまでにはサーバとの接続を切る(ログアウト)必要がある
  • 最悪終わらない場合は、処理を止めるしかない・・・
  • あぁ、、、バックグラウンドで処理させておけば良かった・・・orz

つい先日も、大量のファイルをtarコマンドで圧縮するという処理を実行していました。

当初の目算では、小一時間もあれば終わると思っていたので、フォアグラウンドで処理させていたのですが、処理させていたサーバの性能が低かったこともあり、2時間経っても、3時間経っても終わりません。

そして、上記のような事態に陥りました。

これまでなら、泣く泣くctrl+cを押して処理を強制停止させ、また日を改めて・・・というところだったのですが、この話をうちのエンジニアメンバーに話したところ、私にとっては画期的な解決策を授けてくれました。

サーバ系のエンジニアを20年以上やっていて、こんなのも知らないのかというお話なのですが、同じようなお困りを持っている方も中にはいるかもしれないと思い、恥を忍んで記事にしてみたいと思います。

ctrl+zとjobsコマンドとbgコマンドとdisownコマンド

結論から言うと、Linuxではショートカットのctrl+z、jobsコマンドとbgコマンド、更にdisownコマンドを組合わせることで、フォアグラウンドで実行していた処理をバックグラウンドに移行し、サーバからログアウトしても処理が継続できるようになります。

ctrl+cは処理の強制停止でよく利用すると思いますが、ctrl+zはコンソール上でフォアグラウンドの処理を一時停止させるためのショートカットです。

jobsコマンドは、現在のシェルでバックグラウンドで実行中や、停止中のジョブ(処理)の一覧を表示するコマンドです。

bgコマンドは、ジョブをバックグラウンドで実行するように切り替えるコマンドです。

disownコマンドは、特定のジョブを現在のシェルから分離するためのコマンドです。

この4つを組み合わせると、以下のようなことができるようになります。

  • フォアグラウンドで実行中の処理をバックグラウンド処理に切り替える
  • サーバからログアウト(切断)しても、処理を継続することができる

これまで、一度フォアグラウンドで実行した処理は、完了するまで待つしかない(途中でセッションを切断すると処理も止まるので)と思っていたのですが、この方法を使えば、処理をバックグラウンドに移行させ、且つログアウトすることができます。

実際に試してみる

実際に試してみたいと思います。

今回はサイズの大きい圧縮ファイルをフォアグラウンドで解凍していて、それをバックグラウンドに移行するという例です。

[future@localhost ~]$ ll -h
total 7.1G
-rw-r--r-- 1 future future 7.1G May 17 12:54 test.tgz

[future@localhost ~]$ tar zxf test.tgz

ファイルサイズが7GB程ある、圧縮ファイルを解凍します。

この処理中に、まずはコンソール上でctrl+zを押して、処理を一時停止させます。

[future@localhost ~]$ tar zxf test.tgz
^Z
[1]+  Stopped                 tar zxf test.tgzaaaまとめ

これで、処理が一時停止中になります。

この時のプロセス状態は以下のように、プロセスステータスが「T(停止中)」なっています。

[future@localhost ~]$ ps xa |grep tar
 670202 pts/0    T      0:12 tar zxf test.tgz

この状態で、jobsコマンドを実行するとジョブ番号を見ることができます。

[future@localhost ~]$ jobs
[1]+  Stopped                 tar zxf test.tgz

[数字]の部分がジョブ番号です。今回だとジョブ番号が1になります。

次に、bgコマンドで、この停止中の処理をバックグラウンド処理に移行します。

bgコマンドの引数にジョブ番号を付けて実行するだけです。

[future@localhost ~]$ bg 1
[1]+ tar zxf test.tgz &

これで、このtarの解凍処理がフォアグラウンドからバックグラウンドに移行することができました。

もう一度jobsコマンドとpsコマンドで状況を確認してみます。

[future@localhost ~]$ jobs
[1]+  Running                 tar zxf test.tgz &

[future@localhost ~]$ ps xa |grep tar
 670202 pts/0    S      0:26 tar zxf test.tgz

jobsコマンドで見ると、tarコマンドの一番最後に&が付いて、バックグラウンド処理になったことが分かります。

さて、ここまで出来ると、このままサーバからログアウト(切断)しても大丈夫かと思われるかもしれませんが、このままログアウトすると、登録されているジョブに対してSIGHUPが送られ、ジョブ内容によっては強制終了される場合があります。

これを防ぐために、最後にdisownコマンドを使ってログインシェルからこのジョブを切り離してやることで、SIGHUPを送らないようにしてやることができ、安全にログアウトできるようになります。

実行方法は、disown %[ジョブ番号]です。

[future@localhost ~]$ disown %1

これで、ログインシェルからジョブが切り離されました。

jobsコマンドとpsコマンドで確認してみます。

[future@localhost ~]$ jobs


[future@localhost ~]$ ps xa |grep tar
 672757 pts/0    S      0:06 tar zxf test.tgz

jobsコマンドでは、ジョブが切り離されたので何も表示されませんが、psコマンドではちゃんと処理が継続しているのが確認できます。

これで、フォアグラウンドで実行していた処理をバックグラウンドに移行し、サーバからログアウトしても処理を継続してやることができました。

まとめ

いかがだったでしょうか?

サーバエンジニアをやっていたら、一度は「フォアグラウンドで何かを処理中にサーバからログアウトしたい」といった状況に陥ったことはあるのではないでしょうか?

そんな時、今回の方法を使えば、処理を継続させたまま安全にログアウトすることができます。

Linuxの基本的なショートカットやコマンドですが、ご存じない方もいらっしゃるかもしれないので、何かのご参考になれば幸いです。

個人的には、長年この仕事をやってきて、こんな便利なものを知らなかったのかと、恥ずかしさもあり、感動もありという複雑な気持ちになりました(笑)