web-dev-qa-db-ja.com

PHPスクリプトを起動時に他のサービスが開始した後に実行する

私のRedisデータベースに定期的な天気の更新を取得するために、私が使用しようとしているスキームは次のとおりです

PHPスクリプトは関連するWeather APIから天気を取得します。これは次のようになります

<?php
 function getWeather()
 {
  if (weatherupdaterequired)
  {
   //weather API call
   //parse and store to database
  }
 }

 while (true)
 {
  getWeather();
  sleep(30);
 }
?>

これは/usr/local/binフォルダに保存されています。同じフォルダにシェルスクリプトrunweatherがあります。

#!/bin/sh
Nohup php /usr/local/bin/echoweather.php  >/dev/null 2>&1 &

私は通常#!/bin/bashを使用する傾向がありますが、この例では、起動時に実行すると、以下に示すように#!/bin/shのみが機能することがわかりました。これは、まだ利用できないbashシェルと関係があると思います。

次に、runweatherへのシンボリックリンクを作成しました

ln -s /usr/local/bin/runweather /etc/init.d/runweather

そして別のシンボリックリンク

ln -s /etc/init.d/runweather /etc/rc2.d/S99runweather

いくつかの説明ノート

  1. 実際の作業をすべて行っているのは/usr/local/bin/echoweather.phpです。 30秒間隔で実行され、動作していないときはスリープします
  2. 各実行を終了する直前に、一時的なRedisキー$redis-setEx( "weatherreport"、29、$ echoCount) `を配置します。これを使用して、ヘルスを監視できます。
  3. 起動時にechoweather.phpを実行するシェルスクリプトを/usr/local/binに配置し、それを/etc/init.dにのみシンボリックリンクして/etc/rc2.dに再度シンボリックリンクすると、複雑に見える場合があります。実際のシェルスクリプトを/etc/init.dに配置し、それを/etc/rc2.dにシンボリックリンクすると実行されないことがわかったので、これを行いました。

このスキームは機能しています。私はサーバーを数回再起動し、redis-cliを介してRedisのweatherreportキーを探すことにより、echoweather.phpの状態を確認しました-常に存在し、正しい。ただし、Ubuntuの起動スクリプトを扱う場合、私は素人です。おそらく、もっと簡単な方法がありますか?私はコメントすることができるかもしれない誰にでも多くの義務があります。

1
DroidOS

EOLバージョンのUbuntuを実行していない場合、initシステムはすでにsystemdベースであるため、それを使用するのが正しい方法です。一部の人はType=idleはサービスユニット用ですが、お願いします:(- systemdのマニュアルページ から):

Simple以外のタイプを使用すると、サービスマネージャがサービスの初期化が完了するのを待つ必要があるため、ブートプロセスが遅延する可能性があることに注意してください。したがって、simple以外のタイプを不必要に使用しないことをお勧めします。 (また、長時間実行されるサービスにアイドルまたはワンショットを使用することは一般的に推奨されないことに注意してください。)

これを考慮して、ターゲットと依存関係を設定することにより、サービスの順序を管理する必要があります。スクリプトが機能するには、少なくとも3つの重要な要件があります。

  1. ネットワークスタックが機能している必要があります。
  2. スクリプトはブートプロセスの後半で実行する必要があります。
  3. スクリプトは、Redisが完全に起動した後に実行する必要があります。

これらの要件を特定したら、 systemdターゲット を見てみましょう。これにより、必要なもの、必要なもの、依存する必要があるもの、または待機する必要があるものがわかります。

  1. 構成済みのネットワーク接続を厳密に必要とするユニットは、network-online.target、つまり、ユニットWants thisであり、After thisターゲットのみを実行する必要があります。
  2. multi-user.targetマルチユーザーシステムをセットアップし、それに必要なものがすべて完了すると終了します。したがって、ユニットはおそらくWantsであり、WantedByです。ブートプロセスの後半でユニットを実行したいので、Afterを実行すると、このターゲットも必要になります。
  3. Redisは構成中のマルチユーザーシステムの一部であり、ユニットはRedisが稼働している場合にのみ目的の効果を生み出すことができるため、Requires Redisが実行され、Afterのみをロードする必要があります。

それを念頭に置いて、echoweather.serviceファイルを/etc/systemd/system/このすべてを考慮に入れます:

[Unit]
Description=Gets regular weather updates into my Redis database
Wants=network-online.target multi-user.target
Requires=redis-server.service
After=network-online.target multi-user.target redis-server.service

[Service]
PIDFile=/var/run/echoweather.pid
ExecStart=/usr/bin/php /usr/local/bin/echoweather.php  >/dev/null 2>&1 &
Type=forking
KillMode=process

[Install]
WantedBy=multi-user.target

完了したら、デーモンファイルをリロードし、サービスユニットを有効にして、プロセスを実行します。

$ Sudo systemctl daemon-reload
$ Sudo systemctl enable echoweather.service
$ Sudo systemctl start echoweather.service
3
Alexandre Teles