4

ターミナルから実行するphpスクリプトがあります。これは次のとおりです。

  • データベースからデータの行を取得します (テーブルには、このスクリプトによって特別に処理される JSON 文字列が格納されます)。
  • JSON 文字列を配列に変換し、データベースに挿入するデータを準備します。
  • 必要なデータをデータベースに挿入します

ここにスクリプトがあります:

#!/usr/bin/php
<?PHP
    //script used to parse tweets we have gathered from the twitter streaming API
    mb_internal_encoding("UTF-8");
    date_default_timezone_set('UTC');

    require './config/config.php';
    require './libs/db.class.php';

    require './libs/tweetReadWrite.class.php';
    require './libs/tweetHandle.class.php';
    require './libs/tweetPrepare.class.php';
    require './libs/pushOver.class.php';
    require './libs/getLocationDetails.class.php';

    //instatiate our classes
    $twitdb = new db(Config::getConfig("twitterDbConnStr"),Config::getConfig("twitterDbUser"),Config::getConfig("twitterDbPass"));

    $pushOvr = new PushOver();                                          // push error messages to my phone
    $tweetPR = new TweetPrepare();                                      // prepares tweet data
    $geoData = new getLocationDetails($pushOvr);                        // reverse geolocation using google maps API
    $tweetIO = new TweetReadWrite($twitdb,$tweetPR,$pushOvr,$geoData);  // read and write tweet data to the database

    /* grab cached json row from the ORCALE Database
    *
    * the reason the JSON string is brought back in multiple parts is because
    * PDO doesnt handle CLOB's very well and most of the time the JSON string
    * is larger than 4000 chars - its a hack but it works
    *
    * the following sql specifies a test row to work with which has characters like €$£ etc..
    */
    $sql = "
            SELECT a.tjc_id
                 , dbms_lob.substr(tweet_json, 4000,1) part1
                 , dbms_lob.substr(tweet_json, 8000,4001) part2
                 , dbms_lob.substr(tweet_json, 12000,8001) part3
            FROM twtr_json_cache a
            WHERE a.tjc_id = 8368
            ";

    $sth = $twitdb->prepare($sql);
    $sth->execute();
    $data = $sth->fetchAll();

    //join JSON string back together
    $jsonRaw = $data[0]['PART1'].$data[0]['PART2'].$data[0]['PART3'];

    //shouldnt needs to do this, doesnt affect the outcome anyway
    $jsonRaw = mb_convert_encoding($jsonRaw, "UTF-8"); 

    //convert JSON object to an array
    $data = json_decode($jsonRaw,true);

    //prepares the data (grabs the data I need from the JSON object and does some
    //validation etc then finally submits to the database
    $result = $tweetIO->saveTweet($data); // returns BOOL
    echo $result;
?>

これを端末から実行すると、./proc_json_cache.php正常php proc_json_chache.phpに動作し、UTF-8 でエンコードされたデータがデータベースに到着し、すべて問題なく、データベース内のデータは次のようになります£$@€ < test

CRON経由でこのスクリプトを呼び出すと、データは保存されますが、€£などの特殊文字は単なる四角形であり、データベース内のデータは次のようになります��$@��� < test

これまでに試したことは、次の行を crontab に追加することです。

TERM=xterm
SHELL=/bin/bash

これは、現在のシェル ENV セッション設定と一致し、php スクリプトを呼び出す bash スクリプトに以下を追加したためです。

export NLS_LANG="ENGLISH_UNITED KINGDOM.AL32UTF8"
export LANG="en_GB.UTF-8"

再び現在のシェル ENV 設定に一致させますが、スクリプトを cron から実行した場合とターミナルで直接実行した場合でも、文字エンコーディングの問題が発生します。

これを修正する方法に光を当てることができる同様の問題が他の誰かにありましたか? 前もって感謝します。

編集:

サーバーに関する詳細情報は次のとおりです。

OS: SUSE Linux Enterprise Server 11 PHP:5.2.14

4

2 に答える 2

2

php スクリプトを呼び出す bash スクリプトに追加してみてください。

unset LANG LANGUAGE LC_CTYPE
export LANG=en_GB.UTF-8 LANGUAGE=en LC_CTYPE=en_GB.UTF-8

参照: Re: Crontab の文字セットが utf-8 にない

于 2013-03-18T14:35:17.840 に答える
0

問題を数時間調査した後、シェル セッション変数が PHP スクリプトに渡されていないことに関連しているようです。

忘れていたことの 1 つは、スクリプトが cron ジョブによって直接呼び出されているのではなく、スクリプトが既に実行されているかどうかを確認し、そうでない場合はpcntl_exec()スクリプトの呼び出しに使用される別のデーモン タイプの PHP スクリプトによって呼び出されていることです。

3 番目のパラメーターとして環境設定を渡さなかったので、crontab で設定していたシェル環境設定がスクリプトに渡されない (現在のプロセス空間を共有していた) ことを意味しました。

だから私が実際にやっていたことはこれでした:

pcntl_exec($script, $args); //script take over the process space
                            //but no continued shell env settings

私がすべきだったのは:

$a = get_defined_vars();
pcntl_exec($script, $args, $a['_SERVER']); //script take over the process space
                                           //but with shell env settings continued

詳細については、 pcntl_exec()の php.net マニュアルを参照してください。

于 2013-03-20T19:40:26.607 に答える