CentOS7におけるシェルスクリプトをサービス化する際の質問です。終了指示するまでは何年も永久にサービスを稼働し続けたいのですが、記述に気を付けるべき点を教えてください。


一定時間毎に起動させたい外部と通信するPHPがあります。
cronから呼び出すようにしたところ動作間隔がまちまちでイマイチでした。
そこで、無限ループするシェルスクリプトを記述してPHPを呼び出す際、開始時間と終了時間の差からsleepを入れるようにしたところ、想定通りの間隔で動作するようになりました。
当然ログアウト後も常時動作させたいので /etc/systemd/system に記述したところ(追記に記載します)…当時はサービスとして正常に起動していましたが、数週間後の昨日PHP部分?にて勝手に無限ループが停止しました。

PHPの実行時に何かあったのかもしれませんが…強制終了しようがそれはログに記録しておいて(としていたのに今回はログを調べていても原因が見つからないので困っていますが、それは一旦置きます)、構わず無かったかのように自動でそのまま無限ループを続けさせたいので、何卒よろしくお願い致します。

回答の条件
  • 1人1回まで
  • 登録:
  • 終了:2017/09/07 14:35:07
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。
id:halohalolin

> 当然ログアウト後も常時動作させたいので /etc/systemd/system に記述したところ(追記に記載します)

/etc/systemd/system に call__hogehoge.service として以下のように記述しています。

[Unit]

Description = call__hogehoge daemon

[Service]

ExecStart = /var/www/cron/hogehoge.sh

ExecStopPost = /var/www/cron/hogehoge.sh

Restart = always

Type = simple

[Install]

WantedBy = multi-user.target

※勿論hogehogeの部分は仮名です。

以上よろしくお願い致します。

ベストアンサー

id:uunfo No.2

回答回数63ベストアンサー獲得回数6

ポイント50pt

ExecStopPost = /var/www/cron/hogehoge.sh

これはいらないと思います。

Restart = always

これが入ってるなら異常終了しても再起動するはずなんですが…。
ログに何か出てませんか?

あと無限ループするシェルスクリプトですが、これで一応希望通りの動作はするでしょうけど書き方がすごく変です(echoのタイミングとかphp-cgiとかwaitとか)。

他1件のコメントを見る
id:uunfo

コメントの編集はできませんね。削除して上げなおすしかありません。

php-cgiだとHTTPヘッダーが出力されるので、php-cliを使うべきだと思います。

waitの理由はわかりました。

「無限ループが停止しました」というのは実際にこのシェルスクリプトのプロセスがなくなっていたということでしょうか?
そうでないなら、他と処理のタイミングを合わせるところでデッドロックが発生していた可能性があるように思います。またはPHPの処理が終わらなかったとか。

2017/09/04 22:14:48
id:halohalolin

uuinfoさんありがとうございます。
ログの記録からPHP内に実装していた通信プロセスにおけるタイムアウト処理が怪しいことがわかりましたので、その辺を強化して様子を見ることになりました。

2017/09/23 12:16:19

その他の回答1件)

id:a-kuma3 No.1

回答回数4973ベストアンサー獲得回数2154

ポイント50pt

ずーっと動いているはずのプロセスが止まる原因として、ふたつほど思いつきます。

  • シグナルを受け取った
  • プロセスの制限を超えた

trap でシグナルを捕捉してください。
$? を残しておけば、どのシグナルを受け取ったか分かります。
何らかの理由で外部から受け取ってるかもしれませんし、スクリプト中の echo は PIPE を通してファイルなどに書かれるでしょうから SIGPIPE を受け取る可能性はあります。

プロセスの制限の方は、ulimit で設定するあれです。
/etc/systemd/system/ の [Service] のところで定義できます。

使えるのは、こちらの Limit で始まるやつ。
http://www.ict.griffith.edu.au/teaching/3420ICT/cgi-bin/man.cgi?systemd.directives+7

CPU とか FSIZE とか、上限に達していても不思議ではありません。



後は、考え方を変えてループしない作りにしてみるとか。
sleep した後に、自分自身を nohup でバックグラウンドで起動する。

#! /bin/sh

...
sleep $diference_time

nohup hogehoge.sh &

# もうひとつ呼び出しておいて、自分は終了する

echo は、なにがしかのファイルにめがけて吐きましょう。

id:halohalolin

a-kuma3さんありがとうございます。

シェルスクリプトのサービス割り当て自体今回が初めてなので、ご説明いただいた内容についてまだ意味が理解できていないところがあるのですが、租借させていただきます!

2017/08/31 19:55:49
id:halohalolin

a-kuma3さんありがとうございます。
通信プロセスにおけるタイムアウト処理が怪しいことがわかりましたので、その辺を強化して様子を見ることになりました。

2017/09/23 12:15:09
id:uunfo No.2

回答回数63ベストアンサー獲得回数6ここでベストアンサー

ポイント50pt

ExecStopPost = /var/www/cron/hogehoge.sh

これはいらないと思います。

Restart = always

これが入ってるなら異常終了しても再起動するはずなんですが…。
ログに何か出てませんか?

あと無限ループするシェルスクリプトですが、これで一応希望通りの動作はするでしょうけど書き方がすごく変です(echoのタイミングとかphp-cgiとかwaitとか)。

他1件のコメントを見る
id:uunfo

コメントの編集はできませんね。削除して上げなおすしかありません。

php-cgiだとHTTPヘッダーが出力されるので、php-cliを使うべきだと思います。

waitの理由はわかりました。

「無限ループが停止しました」というのは実際にこのシェルスクリプトのプロセスがなくなっていたということでしょうか?
そうでないなら、他と処理のタイミングを合わせるところでデッドロックが発生していた可能性があるように思います。またはPHPの処理が終わらなかったとか。

2017/09/04 22:14:48
id:halohalolin

uuinfoさんありがとうございます。
ログの記録からPHP内に実装していた通信プロセスにおけるタイムアウト処理が怪しいことがわかりましたので、その辺を強化して様子を見ることになりました。

2017/09/23 12:16:19
  • id:halohalolin
    > 無限ループするシェルスクリプトを記述してPHPを呼び出す

    無限ループするシェルスクリプト /var/www/cron/hogehoge.sh はこんな感じです。

    #!/bin/sh

    PHP_DIR=/var/www/cron/hogehoge/

    if [ "$$" -ne "`pgrep -fo ${0##*/}`" ]; then exit; fi

    cd $PHP_DIR
    while true
    do
    echo "LOOP START"
    start_time=`date +%s`
    /usr/bin/php-cgi hogehoge.php
    echo "PHP END"
    end_time=`date +%s`
    difference_time=$((120 - (end_time - start_time)))
    echo "SLEEP START"
    if [ $difference_time -gt 0 ]; then sleep $difference_time; fi

    echo "WAIT START"
    wait $!
    wait
    echo "WAIT END / LOOP END"
    done

    以上よろしくお願い致します。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません