从PHP调用Ruby脚本时Erubis无法正常工作的问题排查
问题分析与解决方案
首先,这个问题的核心差异在于控制台和PHP子进程的环境变量字符编码设置不同:
- 当你在控制台直接运行
ruby show.rb filename时,终端会话已经配置了UTF-8相关的环境变量(比如LANG、LC_ALL),Ruby会继承这些设置,能正确处理包含非ASCII字符的文件。 - 但PHP运行在Web服务器环境(比如Apache、PHP-FPM)下时,默认的环境编码通常是US-ASCII,Ruby子进程继承了这个编码设置,当读取包含非ASCII字符的模板文件时,就会触发
invalid byte sequence in US-ASCII错误。
修复方法(任选其一即可)
1. 修改Ruby脚本,明确指定编码
你可以在脚本里强制设置文件读取的编码,或者全局设置Ruby的默认编码:
方法1a:读取文件时指定编码
修改show.rb中读取文件的代码,明确指定UTF-8编码:
require 'erubis' f = ARGV[0] puts f # 读取文件时指定UTF-8编码 input = File.read(f, encoding: 'utf-8') eruby = Erubis::Eruby.new(input) puts eruby.result(binding())
方法1b:全局设置Ruby默认编码
在脚本最顶部添加编码声明,同时设置全局默认编码:
# encoding: utf-8 require 'erubis' # 设置全局默认外部/内部编码为UTF-8 Encoding.default_external = Encoding::UTF_8 Encoding.default_internal = Encoding::UTF_8 f = ARGV[0] puts f input = File.read(f) eruby = Erubis::Eruby.new(input) puts eruby.result(binding())
2. 在PHP调用时设置环境变量
如果不想修改Ruby脚本,可以在PHP调用Ruby前,先设置UTF-8相关的环境变量,让Ruby子进程继承:
方法2a:用putenv提前设置
// 设置环境变量为UTF-8 putenv('LC_ALL=en_US.UTF-8'); putenv('LANG=en_US.UTF-8'); // 调用Ruby脚本 system('ruby show.rb filename');
方法2b:在命令中直接指定环境变量
// 在命令开头直接指定环境变量 system('LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 ruby show.rb filename');
为什么控制台正常?
控制台会话启动时,会加载你的shell配置(比如.bashrc、.zshrc),这些配置通常会设置LANG=en_US.UTF-8之类的环境变量,Ruby启动时会读取这些变量,自动使用UTF-8编码处理文件。而Web服务器的进程环境默认不会加载这些用户配置,所以编码是系统默认的US-ASCII,导致了这个差异。
内容的提问来源于stack exchange,提问作者Martin Cup
相关产品推荐
相关产品推荐

