You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache Thrift中PHP CGI脚本报错CGI script exit status 0xff00求助

Python3 CGI运行Thrift PHP服务端遇到的问题

我正在阅读Krzysztof Rakowski所著的《Learning Apache Thrift》一书,在第3章中,作者介绍了如何通过Python CGI在服务端执行PHP脚本,但书中使用的是Python2.7,因此我做了适配修改以兼容Python3。

通过python3 runserver.py命令启动基于Python CGI的Thrift服务端来运行PHP脚本,再用另一个终端执行python3 client.py命令调用客户端。

服务端输出

Starting server on port 8080...
127.0.0.1 - - [30/Oct/2022 11:05:17] "POST /MyFirstServer.php HTTP/1.1" 200 -
127.0.0.1 - - [30/Oct/2022 11:05:18] CGI script exit status 0xff00
127.0.0.1 - - [30/Oct/2022 11:05:18] "POST /MyFirstServer.php HTTP/1.1" 200 -
127.0.0.1 - - [30/Oct/2022 11:05:19] CGI script exit status 0xff00

客户端输出

logged current time to logfile (not waiting for response)
Traceback (most recent call last):
  File "client.py", line 32, in <module>
    product = client.multiply(number1,number2)
  File "gen-py/myfirst/MyFirstService.py", line 79, in multiply
    return self.recv_multiply()
  File "gen-py/myfirst/MyFirstService.py", line 92, in recv_multiply
    (fname, mtype, rseqid) = iprot.readMessageBegin()
  File "thrift-0.17.0/lib/py/build/lib.macosx-10.11-x86_64-2.7/thrift/protocol/TBinaryProtocol.py", line 134, in readMessageBegin
    sz = self.readI32()
  File "thrift-0.17.0/lib/py/build/lib.macosx-10.11-x86_64-2.7/thrift/protocol/TBinaryProtocol.py", line 217, in readI32
    buff = self.trans.readAll(4)
  File "thrift-0.17.0/lib/py/build/lib.macosx-10.11-x86_64-2.7/thrift/transport/TTransport.py", line 68, in readAll
    raise EOFError()
EOFError

相关代码

runserver.py代码

#!/usr/bin/env python

import os
from http.server import HTTPServer, CGIHTTPRequestHandler

class Handler(CGIHTTPRequestHandler):
  cgi_directories  = ['/']

print("Starting server on port 8080...")

HTTPServer(('', 8080), Handler).serve_forever()

client.py代码

#!/usr/bin/env python

import sys, glob
sys.path.append('gen-py')
sys.path.insert(0, glob.glob('thrift-0.17.0/lib/py/build/lib.*')[0])

from myfirst import MyFirstService

from thrift import Thrift
from thrift.transport import THttpClient
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol

from random import randint

try:

    # 'localhost', 8080, '/MyFirstServer.php'
    socket = THttpClient.THttpClient("http://localhost:8080/MyFirstServer.php")
    transport = TTransport.TBufferedTransport(socket)
    protocol = TBinaryProtocol.TBinaryProtocol(transport)
    client = MyFirstService.Client(protocol)
    transport.open()

    # calling log method
    client.log("logfile.log")
    print("logged current time to logfile (not waiting for response)")

    # calling multiply method with random parameters
    number1 = randint(1,100)
    number2 = randint(1,100)
    product = client.multiply(number1,number2)
    print('%dx%d=%d' % (number1, number2, product))

    # calling get_log_size method
    print("current size of logfile is: %d Bytes" % client.get_log_size("logfile.log"))

    # calling get_log_size method second time, but this time with wrong parameter
    print("current size of logfile is: %d Bytes" % client.get_log_size("no_such_file.log"))


    transport.close()

except Thrift.TException as e:
    print("Received following error:\n  error code: %d\n  error desc: %s' % (e.error_code, e.error_description)")

PHP服务端代码

#!/usr/bin/env php
<?php

error_reporting(E_ERROR);

define('THRIFT_PHP_LIB', __DIR__.'/thrift-0.17.0/lib/php/lib');
define('GEN_PHP_DIR', __DIR__.'/gen-php');

require_once THRIFT_PHP_LIB.'/Thrift/ClassLoader/ThriftClassLoader.php';

use Thrift\ClassLoader\ThriftClassLoader;

$loader = new ThriftClassLoader();
$loader->registerNamespace('Thrift', THRIFT_PHP_LIB);
$loader->registerDefinition('myfirst', GEN_PHP_DIR);
$loader->register();


use Thrift\Protocol\TBinaryProtocol;
use Thrift\Transport\TPhpStream;
use Thrift\Transport\TBufferedTransport;

class MyFirstHandler implements \myfirst\MyFirstServiceIf {

    public function log($filename) {
        date_default_timezone_set('UTC');
        $time = date('Y-m-d H:m:s');
        file_put_contents(__DIR__."/" . $filename, $time."\n", FILE_APPEND);
        error_log("Written " . $time . " to " . $filename);
    }

    public function multiply($number1, $number2) {
        error_log("multiply " . $number1 . " by " . $number2);
        return $number1 * $number2;
    }


    public function get_log_size($filename) {
        $filesize = filesize(__DIR__."/" . $filename);
        if ($filesize === false)
            {
                $e = new \myfirst\MyError();
                $e->error_code = 1;
                $e->error_description = "Can't get size information for file " . $filename;
                error_log($e->error_description);
                throw $e;
            }
        error_log("size of log file " . $filename . " is " . $filesize . "B");
        return $filesize;
    } 
};

header('Content-Type', 'application/x-thrift');
echo "\r\n";


$handler = new MyFirstHandler();
$processor = new \myfirst\MyFirstServiceProcessor($handler);

$transport = new TBufferedTransport(new TPhpStream(TPhpStream::MODE_R | TPhpStream::MODE_W));
$protocol = new TBinaryProtocol($transport, true, true);

$transport->open();
$processor->process($protocol, $protocol);
$transport->close();

问题定位分析

CGI script exit status 0xff00通常表示PHP脚本未被正确执行,结合客户端的EOFError(无法读取服务端响应),可从以下几个方向排查:

  1. PHP脚本执行权限与解释器路径

    • 给PHP脚本添加可执行权限:chmod +x MyFirstServer.php
    • 检查脚本首行#!/usr/bin/env php是否有效,用which php获取系统PHP路径,若路径不符,替换首行(比如#!/usr/local/bin/php)
    • 直接在终端运行php MyFirstServer.php,查看是否有语法或依赖报错
  2. HTTP头输出错误

    • PHP脚本中header('Content-Type', 'application/x-thrift');写法错误,正确格式应为header('Content-Type: application/x-thrift');(用冒号分隔键值),错误的头输出会导致Thrift客户端无法解析响应
  3. Thrift依赖路径验证

    • 确认THRIFT_PHP_LIB和GEN_PHP_DIR定义的路径真实存在,且Thrift PHP库与生成的代码文件完整
    • 若直接运行PHP脚本时报类找不到的错误,需修正依赖路径配置
  4. Python CGI环境配置

    • 确保系统已安装PHP且php命令在系统PATH中,Python的CGIHTTPRequestHandler需要能找到PHP解释器来执行脚本

内容的提问来源于stack exchange,提问作者user1503285

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 22:40:40