まず、私は Linux の専門家とはかけ離れているため、ここで問題になる可能性がありますが、とにかく問題は次のとおりです。
ここに書かれていることに従いました:http://symcbean.blogspot.com/2010/02/php-and-long-running-processes.html
実行時間の長い PHP プロセスを起動します。これは、Mac の MAMP 構成で問題なく動作します。しかし、VPS にデプロイすると、非常に奇妙な結果が得られました。
まず、SSH 接続を使用して簡単なテストを行います。
echo '/usr/local/php53/bin/php -d memory_limit=512M -q /home/user/www/Update/Update.php;' | at now + 2minutes
結果:
warning: commands will be executed using /bin/sh
job 2300 at 2012-04-29 19:24
実際、2 分後に php スクリプトが実行されます。ここまでは順調ですね。
次に、次のアプローチを試します。
ブラウザで開きます:
www.myserver.com/Update/LaunchUpdates.php
このphpスクリプトには次の行が含まれています:
exec("echo '/usr/local/php53/bin/php -d memory_limit=512M -q /home/user/www/Update/Update.php;' | at now + 2minutes");
何が起こるかは次のとおりです。 at -l で状態を確認すると、次のように表示されます。
job 2304 at 2012-04-29 19:32
次に、2 分間待ってから、再度 -l で実行します。空の結果が表示されることを期待していますが、代わりに次のようになります。
job 2305 at 2012-04-29 19:34
そして2分後に私は得る
job 2306 at 2012-04-29 19:36
そこで何が起こっているのか、私にはまったくわかりません。php スクリプトは実行されず、ジョブは 2 分後に再スケジュールされたようです。そして、これは私が仕事をするまで何度も続きます。
何が起こっているのか知っている人はいますか?
いくつかの詳細情報:
cat /etc/*-release
Gentoo Base System version 1.6.14
いくつかの詳細。スケジュールされたときの at ジョブの内容は次のとおりです: (at -c [ID])
#!/bin/sh
# atrun uid=1002 gid=100
# mail user 1
umask 33
SERVER_SIGNATURE=\<address\>Apache/2.2.20\ \(Unix\)\ mod_ssl/2.2.20\ OpenSSL/0.9.8o\ Server\ at\ xxx.yyyyy.com\ Port\ 80\</address\>"
"; export SERVER_SIGNATURE
HTTP_USER_AGENT=Mozilla/5.0\ \(Macintosh\;\ Intel\ Mac\ OS\ X\ 10_7_3\)\ AppleWebKit/534.55.3\ \(KHTML,\ like\ Gecko\)\ Version/5.1.5\ Safari/534.55.3; export HTTP_USER_AGENT
HTTP_HOST=xxx.yyyyy.com; export HTTP_HOST
SERVER_PORT=80; export SERVER_PORT
DOCUMENT_ROOT=/home/user/www; export DOCUMENT_ROOT
SCRIPT_FILENAME=/home/user/www/Update/LaunchUpdates.php; export SCRIPT_FILENAME
REQUEST_URI=/Update/LaunchUpdates.php; export REQUEST_URI
SCRIPT_NAME=/Update/LaunchUpdates.php; export SCRIPT_NAME
HTTP_CONNECTION=keep-alive; export HTTP_CONNECTION
REMOTE_PORT=36291; export REMOTE_PORT
PATH=/bin:/usr/bin; export PATH
PWD=/home/user/www/Update; export PWD
SERVER_ADMIN=webmaster@abcdef.com; export SERVER_ADMIN
REDIRECT_STATUS=200; export REDIRECT_STATUS
HTTP_ACCEPT_LANGUAGE=en-us; export HTTP_ACCEPT_LANGUAGE
HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml\;q=0.9,\*/\*\;q=0.8; export HTTP_ACCEPT
REMOTE_ADDR=83.101.41.41; export REMOTE_ADDR
SHLVL=764; export SHLVL
SERVER_NAME=xxx.yyyyy.com; export SERVER_NAME
SERVER_SOFTWARE=Apache/2.2.20\ \(Unix\)\ mod_ssl/2.2.20\ OpenSSL/0.9.8o; export SERVER_SOFTWARE
QUERY_STRING=; export QUERY_STRING
SERVER_ADDR=1.2.3.4; export SERVER_ADDR
GATEWAY_INTERFACE=CGI/1.1; export GATEWAY_INTERFACE
SERVER_PROTOCOL=HTTP/1.1; export SERVER_PROTOCOL
HTTP_ACCEPT_ENCODING=gzip,\ deflate; export HTTP_ACCEPT_ENCODING
REQUEST_METHOD=GET; export REQUEST_METHOD
cd /home/user/www/Update || {
echo 'Execution directory inaccessible' >&2
exit 1
}
/usr/local/php53/bin/php -d memory_limit=512M -q /home/user/www/Update/Update.php;
ジョブが 2 分後に再スケジュールされるのを待っているときに、新しいジョブの内容を取得しますが、次の点を除いて同じです。
SHLVL=764 が SHLVL=765 になりました
より詳しい情報!
ユーザーが提案したように、at の代わりに nohup を使用してみました。だから私がしたことは次のとおりでした:
nohup によって実行されるコマンドを .sh ファイルに生成します (実行権限あり)。そして exec('nohup .....') を実行します
また、LaunchUpdates にチェックを追加して、nohup バッチの実行が完了する前に再度呼び出されないようにしました (基本的に .sh ファイルとそのバッチの最後を rm し、LaunchUpdates でそのファイルの存在をチェックします)。
要するに。
batchProcess.sh には以下が含まれます。
/usr/local/php53/bin/php -d memory_limit=512M -q /home/user/www/Update/Update.php;
rm /home/user/batchProcess.sh
私のLaunchUpdates phpコードには以下が含まれています:
$batchFile = "/home/user/batchProcess.sh";
if (file_exists($batchFile))
{
echo 'Process still running. Try again later!';
exit;
}
exec('nohup /home/user/batchProcess.sh > ~/process.out 2> ~/process.err < /dev/null &');
いいえ、何が起こりますか:
ファイルが実行されずに生成されるように、php スクリプトの exec 行をコメントアウトします。ssh でログインして手動でファイルをテストし、ユーザー「user」に変更して実行します。
nohup /home/user/batchProcess.sh > ~/process.out 2> ~/process.err < /dev/null &
すべて正常に動作します (.sh ファイルは最後に削除されます)。
次に、exec 行のコメントを外して、php スクリプトを再実行します。process.out には以下が含まれます。
Process still running. Try again later!
これは、exec ステートメントではなく、ベーススクリプトを再度実行していることを意味します??? 私はここで完全に迷っています!両方のアカウントで同じ bash スクリプトを実行しているため、どのコマンドが実行されるかに関してエラーは発生しません。
Apache ログを調べ始めるべきですか?
これには少し時間がかかるはずでしたが、少年は私が間違っていました....