3
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

[Bash] 今さらFork爆弾を解析してみる

はじめに

※言わずもがな、お約束の自己責任でお願いします

かの有名なFork爆弾。Bashなら以下です。
:(){ :|: & };:

この原理が今一つピンとこなかったので、今さらながら 動作確認がてら(!)解析してみました。

順番通り(悪く言えばダラダラと)記載していますので、単に読み物(ポエム)としてお読みいただければありがたいです。

本編

読みやすく改変して投下

:の代わりに、関数名としてbombを使います。
bomb() { bomb | bomb & }; bomb

投下で見事に炸裂、再起動が必要となりました。まずは成功?です!

フォアグラウンドで実行してみる

いちいち再起動するのは面倒なので、フォアグラウンドにしてみましょう。

bomb() { bomb | bomb ; }; bomb

こちらも同様に炸裂していますが、Ctrl+C、もしくはターミナルを閉じると何とか復帰できるようです。
解析のため、このフォアグラウンド実行は継続します。

スリープしてみる

同じく解析に手間取りそうなので、10秒くらい待ってみます。

bomb() { sleep 10 ; bomb | bomb ; }; bomb

別のターミナルで確認すると、ゆっくり破滅に向かっていくことが確認できます。
(以下の-bashsleep 10が時間とともにわらわら増えていく)

user@user-VirtualBox:~$ ps -f -u user | grep pts/2
user     25428 25363  0 15:54 ?        00:00:00 sshd: user@pts/2
user     25429 25428  0 15:54 pts/2    00:00:00 -bash
user     26605 25429  0 15:56 pts/2    00:00:00 -bash
user     26606 25429  0 15:56 pts/2    00:00:00 -bash
user     26607 26606  0 15:56 pts/2    00:00:00 sleep 10
user     26608 26605  0 15:56 pts/2    00:00:00 sleep 10
user     26612 25777  0 15:56 pts/3    00:00:00 grep --color=auto pts/2

ログを仕込む

fooというファイルにログを出すようにしてみます。
まだワンライナーで読めますね。

bomb() { sleep 10 ; echo `date +%H:%M:%S.%3N`: Throw 2 bombs... >> foo ; bomb | bomb ; }; bomb

別ターミナルでのログの確認結果:

user@user-VirtualBox:~$ tail -f foo
16:15:14.374: Throw 2 bombs...
16:15:24.378: Throw 2 bombs...
16:15:24.379: Throw 2 bombs...
16:15:34.384: Throw 2 bombs...
16:15:34.385: Throw 2 bombs...
16:15:34.388: Throw 2 bombs...
16:15:34.389: Throw 2 bombs...

何とも素晴らしいログ(自画自賛)!

  1. 16:15:14に2個投下
  2. 16:15:24に2 + 2 = 4個投下
  3. 16:15:34に2 + 2 + 2 + 2 = 8個投下

よって、倍々ゲームで爆弾(プロセス)が増えていることが明確になりました!
10秒スリープしていなかったらと思うと恐ろしいですね!笑

1個にしてみる

誰しも疑問に思うであろう(ですよね?)、1個ならどうなの?です。

bomb() { sleep 10 ; echo `date +%H:%M:%S.%3N`: Throw a bomb... >> foo ; bomb ; }; bomb

ログは当然の結果:

user@user-VirtualBox:~$ tail -f foo
16:28:09.661: Throw a bomb...
16:28:19.664: Throw a bomb...
16:28:29.668: Throw a bomb...

プロセスの確認結果は以下(適当に間隔を空けて確認しています):

user@user-VirtualBox:~$ ps -f -u user | grep pts/2
user     25428 25363  0 15:54 ?        00:00:00 sshd: user@pts/2
user     25429 25428  0 15:54 pts/2    00:00:00 -bash
user     26743 25429  0 16:28 pts/2    00:00:00 sleep 10
user     26746 25777  0 16:28 pts/3    00:00:00 grep --color=auto pts/2
user@user-VirtualBox:~$ ps -f -u user | grep pts/2
user     25428 25363  0 15:54 ?        00:00:00 sshd: user@pts/2
user     25429 25428  0 15:54 pts/2    00:00:00 -bash
user     26748 25429  0 16:28 pts/2    00:00:00 sleep 10
user     26750 25777  0 16:28 pts/3    00:00:00 grep --color=auto pts/2
user@user-VirtualBox:~$ ps -f -u user | grep pts/2
user     25428 25363  0 15:54 ?        00:00:00 sshd: user@pts/2
user     25429 25428  0 15:54 pts/2    00:00:00 -bash
user     26754 25429  0 16:28 pts/2    00:00:00 sleep 10
user     26756 25777  0 16:28 pts/3    00:00:00 grep --color=auto pts/2
user@user-VirtualBox:~$

大元の-bashプロセスはずっと生きていて、sleep 10プロセスが別個に起動していることがわかります(267432674826754)。

すなわち、新しいプロセスは起動しているが、都度前のプロセスが終わっているので、増殖しないということかと。

平たく言ってしまえば、単にbombを繰り返す無限ループですね。

パイプからセミコロンにしてみる

では2つの爆弾の間を、|でなく;にしたらどうなるでしょうか。

bomb() { sleep 10 ; echo `date +%H:%M:%S.%3N`: Throw 1st bomb... >> foo ; bomb ; echo `date +%H:%M:%S.%3N`: Throw 2nd bomb... >> foo ; bomb ; }; bomb

user@user-VirtualBox:~$ tail -f foo
16:42:05.384: Throw 1st bomb...
16:42:15.387: Throw 1st bomb...
16:42:25.390: Throw 1st bomb...

2nd bombまで到達していませんね。これは1st bombをひたすら繰り返しているためで、実体は爆弾1個の場合と同じです。

おわりに

感想(ポエム)

百聞は一見にしかず。愚直な方法ではありましたが、また一つ賢くなりました。笑

確認環境

  • Ubuntu 18.04 LTS(をVMで)
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
Sign upLogin
3
Help us understand the problem. What are the problem?