PHP=スクリプトがシェルでの手動呼び出しから実行されたか(ログインして実行している)か、またはcrontabエントリから実行されたかを検出する方法を探しています。
私のcrontabで実行するように設定した、phpで記述されたさまざまなメンテナンスタイプのスクリプトがあります。ときどき、スケジュールより前に手動で実行する必要がある場合や、何かが失敗したり壊れたりした場合は、数回実行する必要があります。
これの問題は、スクリプトを手動で実行するたびに実行したくないタスク(Twitterへの投稿、電子メールの送信など)に外部通知を設定していることです。
私はphp5(問題がある場合)を使用しています。これは、かなり標準的なLinuxサーバー環境です。
何か案は?
スクリプトがcrontabから実行されたことを検出する代わりに、手動で実行したことを検出する方がおそらく簡単です。
コマンドラインからスクリプトを実行すると、($ _ ENV配列に)環境変数が多数設定されます。これらの内容は、サーバーの設定とログイン方法によって異なります。私の環境では、cronからの実行時に存在しないスクリプトを手動で実行すると、次の環境変数が設定されます。
他にもあります。たとえば、常にSSHを使用してボックスにアクセスする場合、次の行はスクリプトがcronから実行されているかどうかを検出します。
$cron = !isset($_ENV['SSH_CLIENT']);
if (php_sapi_name() == 'cli') {
if (isset($_SERVER['TERM'])) {
echo "The script was run from a manual invocation on a Shell";
} else {
echo "The script was run from the crontab entry";
}
} else {
echo "The script was run from a webserver, or something else";
}
追加のパラメータを設定するか、crontabに行を追加できます。
CRON=running
そして、「CRON」の環境変数を確認できます。また、$ Shell変数を確認してみてください。cronで設定されているかどうかはわかりません。
これは、スクリプトの実行元を見つけるために使用するものです。詳細については、php_sapi_name関数を参照してください: http://www.php.net/manual/en/function.php-sapi-name.php
_$sapi_type = php_sapi_name();
if(substr($sapi_type, 0, 3) == 'cli' || empty($_SERVER['REMOTE_ADDR'])) {
echo "Shell";
} else {
echo "webserver";
}
_
EDIT:php_sapi_name()
にcliが含まれていない場合(cliまたはcli_server)の場合、_$_SERVER['REMOTE_ADDR']
_が空かどうかを確認します。コマンドラインから呼び出される場合、これは空である必要があります。
最も一般的な解決策は、環境変数をcronコマンドに追加して、コードでそれを探すことだと思います。すべてのシステムで動作します。
たとえば、cronによって実行されるコマンドが次の場合:
"/usr/bin/php -q /var/www/vhosts/myuser/index.php"
に変更
"CRON_MODE=1 /usr/bin/php -q /var/www/vhosts/myuser/index.php"
次に、コードで確認できます。
if (!getenv('CRON_MODE'))
print "Sorry, only CRON can access this script";
正しい方法は、たとえばposix_isatty()関数を使用することです。次のようなstdoutファイル記述子:
if (posix_isatty(STDOUT))
/* do interactive terminal stuff here */
PHP=については具体的にはわかりませんが、initまたはcronが見つかるまでプロセスツリーをたどることができます。
PHPが独自のプロセスIDを取得して外部コマンドを実行できると仮定すると、それはps -ef | grep pid
ここでpidは独自のプロセスIDであり、そこから親プロセスID(PPID)を抽出します。
次に、親としてcronに到達するか、親としてinitになるまで、そのPPIDに対して同じことを行います。
たとえば、これは私のプロセスツリーであり、所有権チェーン1-> 6386-> 6390-> 6408が表示されます。
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 16:21 ? 00:00:00 /sbin/init
allan 6386 1 0 19:04 ? 00:00:00 gnome-terminal --geom...
allan 6390 6386 0 19:04 pts/0 00:00:00 bash
allan 6408 6390 0 19:04 pts/0 00:00:00 ps -ef
Cronで実行される同じプロセスは次のようになります。
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 16:21 ? 00:00:00 /sbin/init
root 5704 1 0 16:22 ? 00:00:00 /usr/sbin/cron
allan 6390 5704 0 19:04 pts/0 00:00:00 bash
allan 6408 6390 0 19:04 pts/0 00:00:00 ps -ef
この「プロセスツリーを上る」ソリューションは、cronの下で実行しているかどうかを示すために人工的なパラメーターを導入することを心配する必要がないことを意味します。インタラクティブセッションで実行することを忘れて、物事を詰め込むことがあります。
私が知っていることではありません-おそらく最も簡単な解決策は、スクリプトを呼び出す方法をスクリプトに伝えるために、追加のパラメーターを自分で提供することです。
気味悪い。試す
if (!isset($_SERVER['HTTP_USER_AGENT'])) {
代わりに。 PHPクライアントバイナリは送信しません。用語タイプはPHPがモジュール(つまりApache)として使用される場合にのみ機能しますが、CGIインターフェイスを介してphpを実行する場合は、例を使用してください。上!
私は$_ENV
(var_dump()it)を調べて、それを実行したときとcronjobを実行したときの違いに気付いたかどうかを確認します。それを除けば、何が起こったのかを知らせる「公式の」スイッチはないと思います。
私の環境では、コマンドラインから実行した場合はTERM
が$_SERVER
に設定されていましたが、Apacheを介してWebリクエストとして実行した場合は設定されていませんでした。これをスクリプトの先頭に置き、コマンドラインから実行するか、Webブラウザーからアクセスする場合があります。
if (isset($_SERVER{'TERM'}))
{
class::doStuffShell();
}
else
{
class::doStuffWeb();
}
getenv('TERM')
SOの30文字分のパディング。
別のオプションは、phpファイルがWeb経由で呼び出されたときに設定され、コマンドラインで実行された場合は設定されない特定の環境変数をテストすることです。
私のWebサーバーでは、Apache_RUN_DIR環境変数が次のように設定されているかどうかをテストしています。
if (isset($_ENV["Apache_RUN_DIR"])) {
// I'm called by a web user
}
else {
// I'm called by crontab
}
Webサーバーで機能することを確認するには、次の1つのステートメントを使用して、ダミーのphpファイルをWebサーバーに配置します。
<?php var_dump($_ENV); ?>
次に、1)Webブラウザーでロードし、2)このようにコマンドラインからロードします
/usr/bin/php /var/www/yourpath/dummy.php
違いを比較し、適切な変数をテストします。
Cronコマンドで、スクリプトパスの末尾に?source=cron
を追加します。次に、スクリプトで$_GET['source']
を確認します。
編集:申し訳ありませんが、それはシェルスクリプトなのでqsを使用できません。引数はphp script.php arg1 arg2
の形式で渡し、$argv
で読み取ることができると思います。
$_SERVER['SESSIONNAME']
には、CLIから実行した場合はConsole
が含まれます。多分それは役立ちます。
これはとても簡単です。 cronデーモンは常にMAILTO
環境変数をエクスポートします。それが存在し、空でない値があるかどうかを確認してください-次に、cronから実行します。
posix_isatty(STDOUT) return FALSE
cli呼び出しの出力がリダイレクトされた場合(パイプまたはファイル)...
if(!$_SERVER['HTTP_Host']) {
blabla();
}
私のAmazon Linuxサーバーでは、これは私にとってうまくいきました:
$ isCron =($ _SERVER ['HOME'] == '/');
実行しただけの場合、ホームディレクトリはあなたのものに設定されます。 Sudoを使用して実行する場合、ホームディレクトリは/ rootに設定されます。
コマンドラインで手動で実行しない追加のオプションを指定してcronコマンドを実行する方がよいと思います。
cronは次のようにします。
command ext_updates=1
マニュアルは:
command
スクリプト自体にオプションを追加して、ext_updatesパラメータのデフォルト値をfalseにするだけです。