時々必要になるのですが、多分1ヶ月後ぐらいにまた必要になるのでメモしておきます。
前提条件
- MacOS High Sierra 10.13.3
- PHP7.1.7
今回のお題
PHPで書かれたバッチ集計プログラムがあるとします。
通常は、毎日集計するプログラムでcronで日次実行するように設定済み。トラブル時に再実行可能なように、引数をつけたら指定した日付でも実行可能になっている・・・というよくあるやつ。
この集計プログラムに1項目追加になって、集計値も半年くらい前から見たい=半年分再実行とかいう話になったら、手動で一日ずつやるとかいう忍耐と根性を試されてるみたいな真似はしたくない。というか、しない。
コード
実行されるPHPをdate_test.php,シェルスクリプトをdate_test.shとし、同じディレクトリ内に置いてあるとします。
サンプルなので、実行されるPHP側は、引数が受け取れたことをvar_dumpで確認するだけにしています。
<?php
var_dump($argv);
#!/bin/sh
if [ $# -ne 2 ]; then
echo "引数は2つ指定して下さい"
exit 1
fi
START=$1
END=$2
echo "start script"
TARGET=$START
while :
do
echo $TARGET
php ./date_test.php $TARGET
if [ $TARGET = $END ] ; then
echo "end script"
break
fi
TARGET=`date -d "$TARGET 1day" "+%Y-%m-%d"`
done
最低限のチェックとして引数が2つないと実行しないというのをつけました。
実行
1つ目の引数が集計開始日、2つ目が集計終了日になるように指定
$ ./date_test.sh 2017-07-01 2018-01-31
結果は
start script
2017-07-01
array(2) {
[0]=>
string(15) "./date_test.php"
[1]=>
string(10) "2017-07-01"
}
・・・略・・・
2018-01-31
array(2) {
[0]=>
string(15) "./date_test.php"
[1]=>
string(10) "2018-01-31"
}
end script
になります。
PHP側は、$argvは1つ目がスクリプトの名前になるので、引数は2つ目以降に入ってくるのが注意点ですかね。
日付として正しいかとかのチェックは、PHP側でやるのでもよろし。
シェルスクリプトは途中でechoしてどこまで進んでるかわかるようにするのが個人的にはおすすめです。
あと無限ループを作るときは、いきなりphpを実行するとかはやめて、echoだけにしてお望みの期間がぐるっと回るか確認してあげるとよいかと思います。(被害が少なくて済みますしね・・・)
実行権限は適切に与えてあげてください。誰でも実行できるぜーというのをドキュメントルートに置くとかダメ絶対。(本当にあった怖いお話・・・)
シェルスクリプトについては、参考サイトに貼ったURLで大抵のことは見つかるのでオススメです。
おまけ
Macで上記のような日付計算しようとしたら
usage: date [-jnRu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ...
[-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]
とか言われたので、ちょっと調べて以下のbrewコマンドを実行しました
brew install coreutils
PATH通せってメッセージに出てたので、.bash_profileに
PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
どうやら、Macのdateコマンドは一般的なLinuxと違うらしい・・・
何で実行できないのか、しばらく悩んじゃったじゃないか