Windows(Cygwin)SSH执行远程Ruby脚本报无效字节序列,Mac正常?
这个问题的核心是Cygwin与Mac终端的SSH会话传递的字符编码环境变量不同,导致远程Ruby进程使用的默认编码不一致。Mac终端默认会传递UTF-8相关的环境变量,而Cygwin默认可能用US-ASCII,触发了Ruby的编码错误——即使input.txt是空的,Ruby在处理字符串操作时仍会受默认编码设置影响。
下面是几个针对性的解决方案,按优先级推荐:
1. 直接在Ruby脚本中指定编码
在你的script.rb开头添加编码声明,强制Ruby使用UTF-8处理所有字符串和文件操作:
#!/usr/bin/env ruby # encoding: utf-8 File.open('/home/bob/input.txt').read.gsub(/A/, 'B')
或者更贴合现代Ruby规范的写法:
#!/usr/bin/env ruby # frozen_string_literal: true # encoding: utf-8 File.open('/home/bob/input.txt').read.gsub(/A/, 'B')
这种方法最可靠,完全不受环境变量的影响。
2. 在SSH命令中临时指定编码环境变量
执行SSH命令时,先在远程会话中设置LC_ALL为UTF-8,再运行脚本:
ssh bob@linux-server.com 'export LC_ALL=en_US.UTF-8 && cd ./bin && ./script.rb'
这会临时覆盖远程会话的默认编码设置,让Ruby使用UTF-8进行字符串处理。
3. 永久配置远程用户的编码环境
如果不想每次都手动设置环境变量,可以修改远程服务器上bob用户的shell配置文件(比如~/.bashrc或~/.profile),添加以下内容:
export LC_ALL=en_US.UTF-8 export LANG=en_US.UTF-8
保存后,下次SSH登录时会自动生效,所有后续的Ruby进程都会默认使用UTF-8编码。
4. 显式指定文件读取的编码
修改脚本,在打开文件时明确指定编码,彻底避开环境编码的影响:
#!/usr/bin/env ruby File.open('/home/bob/input.txt', encoding: 'utf-8').read.gsub(/A/, 'B')
这种方法确保文件读取时强制使用UTF-8,即使环境默认编码是US-ASCII也不会报错。
为什么Mac终端执行没问题?
Mac OS的终端默认会将LANG设置为en_US.UTF-8,当你通过SSH连接远程服务器时,这个环境变量会被传递过去,远程Ruby进程会继承这个UTF-8编码设置,所以不会触发US-ASCII的字节序列错误。而Cygwin默认的字符编码环境变量可能是C或US-ASCII,导致远程Ruby使用严格的US-ASCII编码规则,从而抛出错误。
内容的提问来源于stack exchange,提问作者user664833

