Windows 脚本丢到 Linux CI 报错:env: 'bash\r'? 治 CRLF 换行符
本地脚本在 Windows 上跑得好好的,提交到 CI 容器里执行却报错:
env: 'bash\r': No such file or directory
这类问题绝大多数是换行符。Windows 编辑器(记事本、VS Code 默认 CRLF)保存的脚本到了 Linux,行尾多一个 \r,shebang 那行变成 #!/usr/bin/env bash\r,系统会去找名为 bash\r 的解释器,自然找不到。
现象
- 核心报错:
env: 'bash\r': No such file or directory,或-bash: ./install.sh: /bin/bash^M: 坏的解释器: 无法执行 - 明明
ls能看到文件,却报找不到解释器
注意:这跟「没加执行权限」或「bash 没装」无关,别在那些方向上浪费时间。
确认是不是换行符问题
三种快速检测:
cat -A script.sh:行尾出现^M$就是 CRLF(^M是\r的可视化)。纯 LF 只显示$。sed -n '1l' script.sh:第一行若显示#!/usr/bin/env bash\r$即命中。file script.sh:输出含with CRLF line terminators即命中。- 若怀疑还有 UTF-8 BOM:
grep -r $'\xEF\xBB\xBF' . --include='*.sh'。
修复
- 首选 sed(所有发行版都有,容器的 base image 里不一定装了 dos2unix):
sed -i 's/\r$//' script.sh
- 有 dos2unix 时:
dos2unix script.sh
- 改完再执行:
chmod +x script.sh
./script.sh
长期预防
- 仓库根放
.gitattributes,强制 LF:
*.sh text eol=lf
* text=auto eol=lf
.gitattributes 是仓库级生效,比个人 core.autocrlf 配置可靠。
- 编辑器统一:VS Code 右下角把 CRLF 切到 LF,或加
.editorconfig:
end_of_line = lf
- 已入库的历史文件执行
git add --renormalize .统一。 - CI 加一道 lint 拦截,防止回归:
grep -rUl $'\r' *.sh && exit 1