0%

Not able to execute a .sh file: /bin/bash^M: bad interpreter

背景

在搭建某项目CI环境过程中,在Windows下写了个shell脚本,通过winscp传到了gitlab runner所在的Linux工作站上,在工作站上执行该shell脚本时报错:

1
/bin/bash^M: bad interpreter: No such file or directory

知识

错误信息指出,脚本在试图查找位于/bin/bash^M处的解释器时出错:文件或目录不存在。事实也确实如此,目标解释器应该是/bin/bash^M表示回车符(Carriage Return,CR)。

回车符\r本义是光标重新回到本行开头,r的英文return,控制字符可以写成CR,即Carriage Return,十六进制表示为0x0D;换行符\n本义是光标往下一行(不一定到下一行行首),n的英文newline,控制字符可以写成LF,即Line Feed,十六进制表示为0x0AEOL(End of Line)是CRLF的组合,表示到下一行并把焦点移到第一列。

在不同的操作系统这几个字符表现不同:

  • 在Windows系统下,\r \n这两个字符就是表现的本义,即用EOL作为行结尾符;
  • 在类Unix系统下,\n表现为光标下一行并回到行首,即用LF作为行结尾符;
  • 在Mac系统下,\r表现为回到本行开头并往下一行,即用CR作为行结尾符。

至于ENTER键的定义是与操作系统有关的,通常用的Enter是两个加起来。

现实中的具体表现是:

  • Unix/Mac系统下的文件在Windows下打开的话,所有文字会变成一行;
  • Windows下的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。

解决

删除Windows环境下编辑的脚本中的多余\r回车符:

1
sed -i -e 's/\r$//' script.sh

关于Linux中sed命令的使用,可参考此前的一篇文章:《Linux中使用sed命令进行字符串查找和替换》

参考

  1. Not able to execute a .sh file: /bin/bash^M: bad interpreter
  2. The differences between Carriage Return(CR) and Line Feed(LF)
  3. 关于换行符CR(Carriage return) 和 LF(line feed) 的区别

Thank you for your donate!