web-dev-qa-db-ja.com

PHPは、cronジョブから実行されたか、コマンドラインから実行されたかを検出できますか?

PHP=スクリプトがシェルでの手動呼び出しから実行されたか(ログインして実行している)か、またはcrontabエントリから実行されたかを検出する方法を探しています。

私のcrontabで実行するように設定した、phpで記述されたさまざまなメンテナンスタイプのスクリプトがあります。ときどき、スケジュールより前に手動で実行する必要がある場合や、何かが失敗したり壊れたりした場合は、数回実行する必要があります。

これの問題は、スクリプトを手動で実行するたびに実行したくないタスク(Twitterへの投稿、電子メールの送信など)に外部通知を設定していることです。

私はphp5(問題がある場合)を使用しています。これは、かなり標準的なLinuxサーバー環境です。

何か案は?

49
Uberfuzzy

スクリプトがcrontabから実行されたことを検出する代わりに、手動で実行したことを検出する方がおそらく簡単です。

コマンドラインからスクリプトを実行すると、($ _ ENV配列に)環境変数が多数設定されます。これらの内容は、サーバーの設定とログイン方法によって異なります。私の環境では、cronからの実行時に存在しないスクリプトを手動で実行すると、次の環境変数が設定されます。

  • TERM
  • SSH_CLIENT
  • SSH_TTY
  • SSH_CONNECTION

他にもあります。たとえば、常にSSHを使用してボックスにアクセスする場合、次の行はスクリプトがcronから実行されているかどうかを検出します。

$cron = !isset($_ENV['SSH_CLIENT']);

43
Paul Stone
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";   
}
31
MingalevME

追加のパラメータを設定するか、crontabに行を追加できます。

CRON=running

そして、「CRON」の環境変数を確認できます。また、$ Shell変数を確認してみてください。cronで設定されているかどうかはわかりません。

29

これは、スクリプトの実行元を見つけるために使用するものです。詳細については、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']_が空かどうかを確認します。コマンドラインから呼び出される場合、これは空である必要があります。

26
davethebrave

最も一般的な解決策は、環境変数を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";
15
agi

正しい方法は、たとえばposix_isatty()関数を使用することです。次のようなstdoutファイル記述子:

if (posix_isatty(STDOUT))
    /* do interactive terminal stuff here */
15

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の下で実行しているかどうかを示すために人工的なパラメーターを導入することを心配する必要がないことを意味します。インタラクティブセッションで実行することを忘れて、物事を詰め込むことがあります。

6
paxdiablo

私が知っていることではありません-おそらく最も簡単な解決策は、スクリプトを呼び出す方法をスクリプトに伝えるために、追加のパラメーターを自分で提供することです。

5
Dominic Rodger

気味悪い。試す

if (!isset($_SERVER['HTTP_USER_AGENT'])) {

代わりに。 PHPクライアントバイナリは送信しません。用語タイプはPHPがモジュール(つまりApache)として使用される場合にのみ機能しますが、CGIインターフェイスを介してphpを実行する場合は、例を使用してください。上!

5
PeterDerMeter

私は$_ENV(var_dump()it)を調べて、それを実行したときとcronjobを実行したときの違いに気付いたかどうかを確認します。それを除けば、何が起こったのかを知らせる「公式の」スイッチはないと思います。

4
Till

私の環境では、コマンドラインから実行した場合はTERM$_SERVERに設定されていましたが、Apacheを介してWebリクエストとして実行した場合は設定されていませんでした。これをスクリプトの先頭に置き、コマンドラインから実行するか、Webブラウザーからアクセスする場合があります。

if (isset($_SERVER{'TERM'}))
{
    class::doStuffShell();
}
else
{
    class::doStuffWeb();
}
3
Drew Stephens
getenv('TERM')

SOの30文字分のパディング。

2
user213154

別のオプションは、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

違いを比較し、適切な変数をテストします。

2
eosphere

Cronコマンドで、スクリプトパスの末尾に?source=cronを追加します。次に、スクリプトで$_GET['source']を確認します。

編集:申し訳ありませんが、それはシェルスクリプトなのでqsを使用できません。引数はphp script.php arg1 arg2の形式で渡し、$argvで読み取ることができると思います。

1
Adam Hopkinson

$_SERVER['SESSIONNAME']には、CLIから実行した場合はConsoleが含まれます。多分それは役立ちます。

1
Bouke

これはとても簡単です。 cronデーモンは常にMAILTO環境変数をエクスポートします。それが存在し、空でない値があるかどうかを確認してください-次に、cronから実行します。

0
Gabor Garami

posix_isatty(STDOUT) return FALSE cli呼び出しの出力がリダイレクトされた場合(パイプまたはファイル)...

0
Daniel
if(!$_SERVER['HTTP_Host']) {
 blabla();
}
0
Ivor

私のAmazon Linuxサーバーでは、これは私にとってうまくいきました:

$ isCron =($ _SERVER ['HOME'] == '/');

実行しただけの場合、ホームディレクトリはあなたのものに設定されます。 Sudoを使用して実行する場合、ホームディレクトリは/ rootに設定されます。

0
Phil Marshall

コマンドラインで手動で実行しない追加のオプションを指定してcronコマンドを実行する方がよいと思います。

cronは次のようにします。

command ext_updates=1

マニュアルは:

command 

スクリプト自体にオプションを追加して、ext_updatesパラメータのデフォルト値をfalseにするだけです。

0