63

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

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

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

私はphp5(重要な場合)を使用しています。これはかなり標準的なLinuxサーバー環境です。

何か案は?

4

22 に答える 22

47

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

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

  • 学期
  • SSH_CLIENT
  • SSH_TTY
  • SSH_CONNECTION

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

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

于 2008-10-10T13:31:35.367 に答える
45
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";   
}
于 2012-03-19T05:46:58.337 に答える
30

追加のパラメータを設定するか、crontabに行を追加することができます。おそらく次のようになります。

CRON=running

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

于 2008-10-10T10:47:28.703 に答える
30

スクリプトがどこから実行されるかを発見するために私が使用するものは次のとおりです。詳細については、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";
}

編集: cliphp_sapi_name()が含まれていない 場合( cliまたはcli_server の可能性があります)、空かどうかを確認します。コマンドラインから呼び出された場合、これは空でなければなりません。$_SERVER['REMOTE_ADDR']

于 2011-08-26T15:33:07.430 に答える
17

正しいアプローチは、次のように、stdout ファイル記述子などで posix_isatty() 関数を使用することです。

if (posix_isatty(STDOUT))
    /* do interactive terminal stuff here */
于 2010-03-11T22:15:59.260 に答える
17

最も普遍的な解決策は、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";
于 2011-10-23T19:46:09.277 に答える
6

特に PHP についてはわかりませんが、init または cron が見つかるまでプロセス ツリーをたどることができます。

PHP が独自のプロセス ID を取得して外部コマンドを実行できると仮定すると、 pidps -ef | grep 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 で実行しているかどうかを示す人工的なパラメーターを導入することを心配する必要がないことを意味します。

于 2008-10-10T11:10:44.553 に答える
6

気味の悪い。試す

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

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

于 2011-04-15T05:03:43.903 に答える
5

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

于 2008-10-10T10:39:58.487 に答える
5

I would look into $_ENV (var_dump() it) and check if you notice a difference when you run it vs. when the cronjob runs it. Aside from that I don't think there is an "official" switch that tells you what happened.

于 2008-10-10T10:43:53.953 に答える
4

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

if (isset($_SERVER{'TERM'}))
{
    class::doStuffShell();
}
else
{
    class::doStuffWeb();
}
于 2009-05-01T22:59:03.887 に答える
3
getenv('TERM')

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

于 2013-08-23T20:27:13.500 に答える
2

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

編集:申し訳ありませんが、これはシェルスクリプトであるため、qsを使用できません。php script.php arg1 arg2フォームに引数を渡してから、で読み取ることができると思います$argv

于 2008-10-10T10:46:30.610 に答える
1

$_SERVER['SESSIONNAME']ConsoleCLI から実行する場合に含まれます。たぶんそれが役立ちます。

于 2009-01-22T23:35:07.297 に答える
0

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

于 2012-06-23T05:49:35.043 に答える
0

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

于 2010-11-03T16:18:06.820 に答える
0

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

cron は次のようにします。

command ext_updates=1

マニュアルは次のようにします:

command 

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

于 2009-04-27T18:13:04.060 に答える
0
if(!$_SERVER['HTTP_HOST']) {
 blabla();
}
于 2009-01-30T20:03:48.810 に答える
-4

私にとっては簡単です...count($_SERVER['argc'])結果がゼロより大きい場合は、サーバーが不足しています。$_SERVER['argv']次のように、カスタム変数に追加するだけです"CronJob"=true;

于 2011-01-02T06:17:30.967 に答える