Edited at

シェルスクリプトで連続処理をより効率的に

More than 1 year has passed since last update.


想定シチュエーション

日付など連続値で順次処理したい。簡単に効率よく速く処理したい。

【例】

- 20170101~20171231までのログファイルがあって、それぞれに処理を行いたい。

- sh execute.sh -d 20170101 で 1日分の処理が行える。


なにも考えないと


01.sh

sh execute.sh -d 20170101

sh execute.sh -d 20170102
(中略)
sh execute.sh -d 20171231

Excelで365行のコマンドを作って処理。だれもがやったことがあるのでは。


脱Excel


02.sh

STARTYMD=20170101

ENDYMD=20171231

TD=${STARTYMD}
ENDYMD=`date -d "${ENDYMD} 1 days" '+%Y%m%d'` # 便宜上+1日してるだけ。
while [ ${TD} -ne ${ENDYMD} ]; do
sh execute.sh -d ${TD}
TD=`date -d "${TD} 1 days" '+%Y%m%d'`
done


日付を追うのはdateコマンドに任せる。日付ではなく連番であれば単にforを使う。


02-2.sh

STARTNUM=1

ENDNUM=10

for NUM in $(seq ${STARTNUM} ${ENDNUM}); do
sh execute.sh -n ${NUM}
done



CPUを効率的に

上記では1コアしか使わず、今どきのPC/Serverでは力を持て余すので、コア数分だけ分ける。


03child1.sh

STARTYMD=20170101

ENDYMD=20170331
(略)


03child2.sh

STARTYMD=20170401

ENDYMD=20170630
(略)


03child3.sh

STARTYMD=20170701

ENDYMD=20170930
(略)


03child4.sh

STARTYMD=20171001

ENDYMD=20171231
(略)


command

$ sh 03child1.sh &

$ sh 03child2.sh &
$ sh 03child3.sh &
$ sh 03child4.sh &

これで4コア並行で使える。


並列処理も自動に


04.sh

STARTYMD=20170101

ENDYMD=20171231

THREADS=$(nproc --all) # コア数取得
TD=${STARTYMD}
ENDYMD=`date -d "${ENDYMD} 1 days" '+%Y%m%d'` # 便宜上+1日してるだけ。
while [ ${TD} -ne ${ENDYMD} ]; do
sh execute.sh -d ${TD} & # バックグラウンドにしてしまう。
while [[ $(jobs | wc -l) -ge ${THREADS} ]]; do sleep 1; done # コア数まで処理中になったら待つ
TD=`date -d "${TD} 1 days" '+%Y%m%d'`
done
wait # これを付けるとすべての処理の完了を待つ


今どきは32コアマシンとかポチポチで起動できちゃうので、1サーバでさっと処理できるようになって便利ですね。