ansible远程执行脚本编码乱码本质是控制节点、ssh传输、被控节点终端环境三者字符编码不一致所致,需统一为utf-8:调整终端工具编码设置、确保被控节点locale启用utf-8、playbook中通过environment注入lang/lc_all、验证并转换脚本自身编码。

Ansible 远程执行脚本时出现编码乱码,本质是控制节点、SSH 传输过程、被控节点终端环境三者之间字符编码不一致导致的,不是 Ansible 本身的问题,但会直接影响脚本输出可读性(比如中文注释、日志、变量值显示为或问号)。排查需从终端配置、SSH 通信、远程环境三端入手。
检查并统一 SSH 终端的字符编码设置
SecureCRT、Xshell、WindTerm 等工具默认可能使用 GBK 或 ISO-8859-1,而 Linux 主机普遍用 UTF-8。若终端编码与远程 shell 不匹配,即使脚本正常执行,输出也会乱码。
- 在 SecureCRT 中:右键会话 → Options → Session Options → Terminal → Appearance → Character Encoding,选 UTF-8
- 在 WindTerm 中:设置 → 终端 → 字符编码 → 设为 UTF-8
- 临时验证:连接后运行
echo $LANG,应返回类似en_US.UTF-8或zh_CN.UTF-8;若为C或空,说明未启用 UTF-8
确保被控节点系统 locale 完整启用 UTF-8
Ansible 任务(尤其是 shell、command、script)在远程主机上以非交互式 shell 执行,默认可能不加载用户 profile,导致 LANG 为空或回退到 C locale,从而无法正确处理 UTF-8 字符。
- 登录被控节点,运行
locale -a | grep -i utf8,确认存在如en_US.utf8或zh_CN.utf8 - 若缺失,生成 locale:
sudo locale-gen en_US.UTF-8(Ubuntu/Debian)或sudo localectl set-locale LANG=en_US.UTF-8(RHEL/CentOS 8+) - 在 Ansible Playbook 中强制指定环境变量(推荐):
- name: Run script with UTF-8 locale shell: /path/to/script.sh environment: LANG: en_US.UTF-8 LC_ALL: en_US.UTF-8
避免脚本自身引入编码问题
即使环境统一,脚本若用非 UTF-8 编码保存(如 Windows 记事本默认 ANSI/GBK),上传后执行仍会乱码——尤其涉及中文 echo、sed 替换、cat 输出等场景。
- 用
file -i script.sh检查脚本实际编码;若显示charset=gbk或charset=iso-8859-1,需转为 UTF-8:iconv -f GBK -t UTF-8 script.sh > script_utf8.sh - 在脚本首行添加 shebang + 编码声明(虽非 POSIX 标准,但部分解释器识别):
#!/bin/bash\n# -*- coding: utf-8 -*- - Ansible 的
copy模块默认按二进制传输,不会改编码;确保源文件本身就是 UTF-8 格式再分发
验证 Ansible 执行时的环境一致性
Ansible 默认以非登录、非交互方式调用远程 shell(如 /bin/sh -c),不读取 ~/.bashrc 或 /etc/profile,因此不能依赖用户级 locale 配置生效。
- 在 Playbook 中加一个调试任务,确认远程执行时的真实环境:
- name: Check remote locale and encoding shell: locale && echo "LANG=$LANG" && echo "LC_ALL=$LC_ALL" && python3 -c "import sys; print(sys.getdefaultencoding())" register: env_check - name: Show encoding info debug: var: env_check.stdout_lines - 如果发现
LANG为空,优先通过environment:注入,而非修改被控节点全局配置——更安全、更可控











