WordPress Twenty Seventeen
WordPress の wp-cron.php を止め
Raspberry Pi の cron で 代替する
色々と調べていくと、まだまだやるべき事が出てくるもで、深掘りする重要性に改めて気づかされる。
「wordpress の wp-cron.php は、アクセスの度に呼び出されている」
これを停止することによって、パフォーマンスが向上する。
以下、WordPress の wp-cron.php を止め、Linux の cron で代替した記録。
1. wp-cron.php とは
wp-cron.php は、
時間と連動した処理で起動されるスクリプトで、
・記事の予約投稿
・メール投稿
・XML-Sitemap
などで使用される。
wp-cron.php は、Dos攻撃などの不正アクセスに利用されることがあり、アクセス制限を掛ける方が良い。
問題は、
アクセスが発生する度に起動されるので、アクセス数が増えると、サーバへの負荷が掛かってしまう。
例えば、ユーザーがサイトにアクセスすると wp-config.php が起動され、予約投稿の記事が無いかを確認する。毎回これが行われるので、アクセス数が多いサイトだと、サイトのパフォーマンスにも大きく影響する。
→ wp-config.php 自体を無効にすることが推奨されている。
Webへのアクセスをトリガーとして、現在実行すべき処理がないかどうかをその都度確認するもの。
「予約投稿」は、Webへのアクセスが無ければ、時間が過ぎても投稿されない。
2. nginx のアクセスログを見る
nginxのアクセスログから、特定の文字列「wp-cron.php」が含まれるログを参照する。
sudo cat /var/log/nginx/access.log | grep wp-cron.php
nginxのアクセスログから「wp-cron.php」を抜き出した例。
上記例は一部だが、「wp-cron.php」には非常に多くのアクセスがあることが確認できた。
※:nginxのアクセスログを出力する方法。
(server ディレクティブに記述した。)
access_log /var/log/nginx/access.log;
3. wp-cron.php を止める
「wp-config.php」を編集する。
(WordPressを導入したディレクトリーの直下にある。)
sudo nano /home/yaopi/www/wordpress/wp-config.php
「wp-config.php」の「define(‘DB_COLLATE’, ”);」の下辺りに、以下の記述を追記する。
define('DISABLE_WP_CRON', 'true');
「wp-config.php」への追記例。
4. linux の cron で代替する
「wp-config.php」の停止による弊害を防ぐために、下記のように Raspberry Pi の cronで1時間に1回ほど、定期的に「wp-config.php」を実行する設定を行う。
方法-1:HTTP / HTTPS経由での実行。
sudo crontab -e
35 * * * * curl https://arakan60.site/wp-cron.php > /dev/null 2>&1
上記例は、毎時35分に HTTPS経由で「wp-config.php」を実行する設定。
(wp-cron.php は、WordPressをインストールしたディレクトリの直下にある)
nginxのアクセスログを見ると、「wp-cron.php」が1時間毎に実行されるようになった。
HTTP / HTTPS経由での実行は、望ましくありません。
Webサーバー経由でアクセスすると、その分サーバーにオーバーヘッドが生じます。Webサーバーは、通信時に全体のコンテンツの長さを計算してレスポンスヘッダーに記載したり、圧縮処理を実行したり、名前解決などでネットワークを経由したり、キャッシュサーバーを利用している場合はトラフィック自体がネットワーク上を流れてしまったりするなど、様々な点でコマンドでの実行と比べ動作が遅くなる可能性を孕んでいます。また、Webサーバーが起動していないと動作せず、エラーを吐きます。
なお、この方法の場合は処理自体がWebサーバーを経由する(WebサーバーのユーザーがPHPファイルを読み込む)ため、rootユーザーで実行しても大丈夫です。
方法-2:シェルスクリプトで「wp-cron.php」へのパスを指定して実行。
シェルスクリプトの作成。
(/etc/cron.hourlyの中に、名前:wp-cron.shで作成。)
sudo nano /etc/cron.hourly/wp-cron.sh
シェルスクリプトの内容。
#!/bin/sh
cd /; /usr/bin/php -q /home/yaopi/www/wordpress/wp-cron.php >/dev/null 2>&1
シェルスクリプトに実行権限を与える。
sudo chmod +x /etc/cron.hourly/wp-cron.sh
実際に動かしてみる。
/etc/cron.hourly/wp-cron.sh
crontab への登録(毎時35分に、シェルスクリプトを実行)。
sudo crontab -e
35 * * * * /etc/cron.hourly/wp-cron.sh
5. 方法-2のシェルスクリプトと実行結果
cron で実行する「シェルスクリプト」。
/usr/bin/php -q /home/yaopi/www/wordpress/wp-cron.php >/dev/null 2>&1
①.「/usr/bin/php」の部分は、PHPコマンドのパスを指定。
php パスの確認要領。
which php
php のパスを確認した例。
②.
PHP コマンドラインオプション 【-q】
"-q"オプションを付けることで、HTTPヘッダを自動出力させないようにする。
③.「/home/yaopi/www/wordpress/wp-cron.php」の部分は、WordPressをインストールしたディレクトリで、wp-cron.phpファイルへのフルパスを指定。
(wp-cron.php は WordPressをインストールしたディレクトリの直下にある)
④.
/dev/null(nullデバイスとも呼ばれる)とは
UNIXやUnix系オペレーティングシステム (OS) におけるスペシャルファイルの1つで、そこに書き込まれたデータを全て捨て(writeシステムコールは成功する)、読み出してもどんなプロセスに対してもデータを返さない(EOFを返す)。
/dev/null は通常、プロセスの不要な出力ストリームを捨てるのに使う。
⑤.
>/dev/null 2>&1
①標準出力
標準出力だけを出す場合
/path/script.sh 1> /path/exec.log
②エラー出力
エラー出力だけ出す場合
/path/script.sh 2> /path/error.log
③標準出力とエラー出力その1
両出力を一つのファイルに出す場合
/path/script.sh > /path/both.log 2>&1
④標準出力とエラー出力その2
それぞれの出力を別々のファイルに出す場合
/path/script.sh 1> /path/exec.log 2> /path/error.log
この「シェルスクリプト」を cron で実行すると、問題が発生。
問題点-1:
上記設定で、【 cron 】は正常に起動・稼働するが、
【 cron のログ 】が書き出されない。
WEBサーバーの、実行ユーザーの確認要領。
ps aux | grep httpd
php のパスと、WEBサーバーの実行ユーザーを確認した例。
問題点-2: ユーザーを指定すると、ログが書かれるがエラーになる。
35 * * * * ユーザー /etc/cron.hourly/wp-cron.sh
エラーメッセージ。
(CRON) error (grandchild #4525 failed with exit status 127)
crontab で、「ユーザー指定」をして登録。
sudo crontab -u yaopi -e
※:注意
ユーザー指定した「crontab」は、別に作られるので、
【 sudo crontab -e 】では編集できない。
crontab への登録結果。
シェルスクリプトの内容。
「
ユーザー指定」をして登録すると、エラーが出なくなる。
「
ユーザー指定」をしたcronの設定は「/var/spool/cron/crontabs/[ユーザ名]」で保存されている。
crontabコマンドの使い方。
6. cron のログを確認
cron のログは、デフォルトでは出力されないようになっている。
cron のログを出力するように設定。
sudo nano /etc/rsyslog.conf
cron のログ行がコメントアウトされているので、 # を消す。
cron のログレベルを設定する。
sudo nano /etc/default/cron
全て表示する様に、足して15にする:EXTRA_OPTS='-L 15'。
rsyslog の変更後は、再起動が必要。
sudo /etc/init.d/rsyslog restart
cron のログファイルを確認する方法。
sudo nano /var/log/cron.log
sudo cat /var/log/cron.log
sudo tail -f /var/log/cron.log
cron のログファイルの内容。
7. cron に関するコマンド
稼働状況の確認。
/etc/init.d/cron status
systemctl status cron.service
自動実行の設定。
chkconfig --level cron on
自動起動設定の確認。
chkconfig --list cron
run level 2~5 で cron サービスが自動起動に設定されていることが分かる
cron に設定を再読み込みさせる。
/etc/init.d/cron reload
cron の再起動。(cron の設定を行ったら、必ず再起動する。)
sudo /etc/init.d/cron restart
cron ログファイルの確認。
sudo nano /var/log/cron.log
sudo cat /var/log/cron.log
sudo tail -f /var/log/cron.log
cron 設定ファイルの編集。(紛らわしいので注意。)
sudo nano /etc/crontab
「/etc/crontab」
「etc」ディレクトリの中の「crontab」ファイルで、「crontab -e」コマンドで編集されるcrontabファイルとは別物。
「crontab -e」コマンドで編集されるcrontabファイルは「/var/spool/cron/【ユーザ名】」になる。
7. rsyslog に関するコマンド
cron のログが、無い!。
cron のログファイルを確認
→ 【reboot】以降、cron のログが書かれていない。
原因:rsyslogサービスが【 inactive 】になっている。
→ syslogサービスは、自動起動になっていない。
「chkconfig」で、自動起動するサービスを確認してみる。
「rsyslog」は、【off】になっている。
「rsyslog」の自動起動設定。
sudo systemctl enable rsyslog.service
「rsyslog」自動起動設定の確認。
chkconfig --list rsyslog
「rsyslog」の自動起動設定と確認事例。
「rsyslog」の自動起動設定を行うと、【reboot】後も cron のログが書かれるようになった。
「rsyslog」の自動起動の解除。
sudo systemctl disable rsyslog.service
rsyslog サービスの再起動。
sudo service rsyslog restart
プロセスID、プロセスが開いているファイルを確認。
ps -ef | grep rsyslog
ps [option]
-e : 実行中のすべてのプロセスを表示
-a : すべてのプロセスを表示
-f : 完全( full )リストを作成します
-l : ロング形式出力を生成します
「rsyslogd」
システムのログを記録するデーモン。「syslog」と呼ばれる。
syslogdの代わりに「rsyslogd」が動いている。
syslogの内容表示。
sudo cat /var/log/syslog
以上。
(2020.10.07)