事象と実施したこと
まずApacheの再起動を試みました。 [admin@hogehoge ~] sudo service httpd restart
実施するも前述通り、立ち上がらず。エラーログを確認します。
[admin@hogehoge ~] vi /var/log/httpd/error_log
[Wed Feb 14 08:58:53 2024] [error] (28)No space left on device: Cannot create SSLMutex
すると「(28)No space left on device: Cannot create SSL Mutex」のエラーが確認できます。こちらはセマフォを使い切ったときに出るエラーです。
セマフォの状況は「ipcs -s」で確認できます。
[admin@hogehoge ~] sudo ipcs -s
------ Semaphore Arrays --------
key semid owner perms nsems
0x00000000 0 root 600 1
0x00000000 32769 root 600 1
0x00000000 671449090 apache 600 1
0x00000000 671481859 apache 600 1
0x00000000 671514628 apache 600 1
0x00000000 672333829 apache 600 1
0x00000000 672366598 apache 600 1
0x00000000 672399367 apache 600 1
0x00000000 674791432 apache 600 1
0x00000000 674824201 apache 600 1
0x00000000 674856970 apache 600 1
セマフォとは
セマフォは、ある資源が何個使用可能かを示す記録と考えればわかりやすく、それにその資源を使用する際や解放する際にその記録を「安全に」(すなわち競合状態となることなく)書き換え、必要に応じて資源が使用可能になるまで待つ操作が結びついている。セマフォは競合状態を防ぐ便利なツールであるが、セマフォを使うことでプログラムにおける競合状態がなくなると保証するものではない。wikipediaよりつまり、セマフォは、プログラムの並行処理を制御するための同期手法で、共有リソースへのアクセスを管理します。
こちらがいっぱいになり起動できなくなっている現象です。 現在セマフォの最大値がいくつに設定されているかは以下コマンドで確認できます
[admin@hogehoge ~] sudo /sbin/sysctl -a | grep sem
kernel.sem = 250 32000 32 128 (最大値は128)
Apacheが起動できない状態で、apacheのセマフォが溜まっているときは以下のコマンドでクリア可能です。
[root@hogehoge ~] ipcs -s | grep apache | awk ' { print $2 } ' | xargs ipcrm sem
対策
めったにセマフォが溢れることはないのですが、今後起きたときのためにシェルスクリプトで監視するようにしました。 以下コマンド実行時、現在のセマフォ利用数をチェックして、しきい値を超えていたらセマフォのクリアを実施。Apacheの状態を確認して起動してなかったら再起動するようにしています。 #!/bin/bash
SEMAPHORE_NAME="apache"
THRESHOLD=100
SEMAPHORE_COUNT=$(ipcs -s | grep "$SEMAPHORE_NAME" | wc -l)
send_mail() {
local subject="Semaphore Count Alert"
local recipient="admin@example.jp"
local body="Semaphore count exceeds the threshold. Current count: $1"
echo "$body" | mail -s "$subject" "$recipient"
}
if [ "$SEMAPHORE_COUNT" -gt "$THRESHOLD" ]; then
echo "Semaphore count exeeds the threshold."
echo "Clearing semaphores..."
ipcs -s | grep "$SEMAPHORE_NAME" | awk '{print $2}' | xargs -r ipcrm sem
echo "Semaphores cleared."
APACHE_STATUS=$(service httpd status)
send_mail "$SEMAPHORE_COUNT"
if [[ $APACHE_STATUS != *"running..."* ]]; then
echo "Apache is not running"
service httpd restart
else
echo "Apache is already running."
fi
fi
こちらはセマフォを監視するユーザーを指定します。
SEMAPHORE_NAME="apache"
こちらはセマフォの数が何個以上になったらセマフォを消すかのしきい値を指定します。
THRESHOLD=100
セマフォクリア時、メール通知をするアドレスを指定します。適宜置き換えてください。
local recipient="admin@example.jp"
※メールは送らなくて良い場合は「send_mail “$SEMAPHORE_COUNT”」を削除してください。