私は私のシステムをフォーク爆弾でより弾力的にしたいと思います。これは、systemdの引数を使用するか、cgrulesengdを介してすべての有効なシェルのコントローラをDefaultTasksMax
使用して部分的に達成できます。cgroup
pids
*:bash pids users/shells/bash/
*:zsh pids users/shells/zsh/
シェル制限を設定するための小さなスクリプトもあります。
CGDIR=/sys/fs/cgroup/
mkdir -p $CGDIR/pids/users/shells/
echo '8192' > $CGDIR/pids/users/shells/pids.max
mkdir -p $CGDIR/pids/users/shells/bash/
echo '2048' > $CGDIR/pids/users/shells/bash/pids.max
mkdir -p $CGDIR/pids/users/shells/zsh/
echo '1024' > $CGDIR/pids/users/shells/zsh/pids.max
bashシェルを使用して端末を起動して:(){ :|:& };:
実行すると、何も起こりません。pids.current
50〜60%のCPU使用率でほぼ即座に2048を取得します。ターミナルを閉じるとフォークボムが消え、すべてが正常に戻ります。
zshシェルを使用して端末で同じ操作を実行したい場合は、すぐに100%CPUを使用して端末を閉じた後でも、フォーク爆弾が原因でシステムがシャットダウンします。この問題を解決する唯一の方法は、異なるシェルを持つkillall -9 zsh
端末でコマンドを複数回実行することです。
bashでフォーク爆弾が死んでいるように、なぜzshで死ぬことができないのですか?つまり、ターミナルを閉じると爆弾が爆発します。
答え1
EAGAINが失敗したbash
場合fork()
は、制限に達した場合(setrlimitを使用するか、対応するcgroup pid制限を使用)、スリープモードに切り替え、bash
1秒後に再試行してから2秒後(再度失敗した場合)、4秒後にスリープモードに切り替えます。 8秒間さらにフォーク(!)を試みずに放棄します。
その後、bash
制限に達すると(静かなシステムでは1秒未満)、ほとんどのbashがスリープモードで処理されます。これがフォーク爆弾がbash
他の砲弾よりもはるかに悪い理由です。
端末を閉じても、これらのプロセスは終了しません。おそらくあなたが見ているのは、15秒が少し以上の時間(1+2+4+8)後にフォーク爆弾が消えることです。この時点で正常に開始され、スリープモードに移行したすべてのプロセスは、開始してから8秒後に同時に終了します。 4番目のフォークの試み。
ではzsh
再試行モードとスリープモードがなく、すべてのプロセスが分岐して終了します。プロセスが終了すると、フォークされたプロセスの1つで使用できるようにプロセスが解放されます。
フォーク爆弾を終了したい場合、最も簡単な方法はプロセスグループ全体を終了することです。これは、プロセスのリストを収集し、各プロセスに対して個別にシャットダウンを送信する必要があるkillall
ため実現できません。killall
すべてのプロセスがスリープモードの場合は問題ありませんが、bash
プロセスが常に作成され、各シャットダウンの間に開始できる他のシェルには適していません。
を使用してpgidを取得し、ps -j
を使用してプロセスグループを終了できますkill -- "-$pgid"
。