执行脚本而非source时Locale异常(POSIX替代UTF-8)的解决咨询
这个问题我之前也碰到过,核心原因很明确:直接用./myscript.sh执行脚本时,系统会启动一个非交互式、非登录的子Shell,这类Shell默认不会加载你交互式会话里的Locale配置(比如~/.bashrc里的设置);而source脚本是在当前的交互式Shell里运行,自然能继承所有已设置的环境变量,包括Locale。
下面是几个可行的解决办法,你可以根据自己的需求选择:
1. 在脚本开头显式设置Locale
如果不想改动全局配置,最简单的方法就是在脚本的最顶部直接导出需要的Locale变量,比如:
#!/bin/bash # 替换成你实际使用的Locale,比如zh_CN.UTF-8 export LANG=en_US.UTF-8 export LC_ALL=en_US.UTF-8 # 后面是你的脚本逻辑
这样不管子Shell继承了什么环境变量,脚本都会强制使用你指定的UTF-8 Locale。
2. 把Locale配置移到子Shell能继承的位置
默认情况下,非交互式Shell不会加载~/.bashrc,但会继承父Shell的环境变量。如果你的Locale是在~/.bashrc里设置的,建议把这些配置移到~/.profile或者~/.bash_profile(针对bash),或者系统级的/etc/profile里——因为登录Shell会加载这些文件,而你的终端会话通常是登录Shell,它的子Shell(比如执行脚本时的Shell)会继承这些环境变量。
举个例子,把这两行从~/.bashrc移到~/.profile:
export LANG=en_US.UTF-8 export LC_ALL=en_US.UTF-8
之后重启终端或者执行source ~/.profile,再运行脚本应该就能拿到正确的Locale了。
3. 配置系统级Locale(推荐)
如果希望所有用户的所有Shell会话都使用正确的Locale,可以修改系统级配置文件:
- 对于大多数基于systemd的发行版(比如Ubuntu 18.04+、CentOS 7+),编辑
/etc/locale.conf:LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 - 对于Debian/Ubuntu老版本,编辑
/etc/default/locale,内容同上。
保存后执行locale-gen(如果系统提示需要生成Locale的话),然后重新登录系统,这样不管是交互式还是非交互式Shell,都会默认使用正确的UTF-8 Locale。
验证方法
修改后可以在脚本里加一行locale命令,执行脚本后看输出,确认LANG和LC_*系列变量都是你期望的UTF-8值,而不是POSIX。
内容的提问来源于stack exchange,提问作者basickarl

