行尾符
问题
问题描述:
由于云堡垒机在使用vim编辑shell脚本粘贴多行内容时会出现内容部分丢失,所以我先在Windows的记事本上编写了unzip_recursive.sh.txt,在上传到云堡垒机,去掉.txt 后缀执行脚本,发现报错。
1 | [root@kf-zgttslyypt-tyszr-xzzs unzip-area]# ll |
报错原因:
这个错误是因为脚本文件的行尾符(line endings)问题。在 Windows 或类 Windows 系统中编辑了脚本,导致文件包含了 CRLF(\r\n)行尾符,而 Linux 系统只需要 LF(\n)行尾符。
错误信息中的 ^M 就是 CR(Carriage Return)字符在 Linux 中的显示。
解决方案:
使用 sed 命令删除 CR 字符
1 | sed -i 's/\r$//' unzip_recursive.sh |
预防措施:
为了避免将来再次出现这个问题:
- 在 Linux 中编辑脚本:使用
vim、nano等 Linux 原生编辑器 - 如果必须在 Windows 中编辑:
- 使用 VS Code,并在右下角状态栏选择 “LF” 而不是 “CRLF”
- 使用 Notepad++,设置:编辑 → 文档格式转换 → 转换为 Unix 格式
- Git 配置:如果你使用 Git,可以设置:
1 | git config --global core.autocrlf input |
相关知识
行尾符
行尾符,也叫做换行符,是嵌入在文本文件中的不可见字符,它的作用是告诉计算机“一行文本在这里结束,新的一行从这里开始”。
你可以把它想象成写作时的“回车换行”操作:在纸上写完一行字后,你把笔移回本行的开头(回车),然后向下移动一行(换行)。
不同的操作系统在发展过程中选择了不同的字符来表示行尾符:
| 操作系统 | 行尾符符号 | 转义序列 | 说明 |
|---|---|---|---|
| Unix / Linux / macOS (现代) | LF (Line Feed) |
\n |
仅使用“换行”一个字符 |
| Windows / DOS | CRLF (Carriage Return + Line Feed) |
\r\n |
使用“回车”+“换行”两个字符 |
| Classic Mac OS (旧版本) | CR (Carriage Return) |
\r |
仅使用“回车”一个字符 |
历史原因:
在古老的打字机/电传打字机上,“回车”和“换行”确实是两个独立的机械动作。
Windows 继承了 DOS 的传统,使用了两个字符(
CRLF)来完成这一操作。Unix 设计者认为一个字符(
LF)就足够了,更简洁。
让我们看看你遇到的错误信息:
1 | -bash: ./unzip_recursive.sh: /bin/bash^M: bad interpreter: No such file or directory |
这里的 ^M 就是问题的关键!
- 在Linux的显示中,
\r(Carriage Return)字符会被显示为^M。 - 所以,脚本的第一行
#!/bin/bash在Linux看来实际上是#!/bin/bash\r。 - 当Bash尝试执行时,它寻找的解释器路径就变成了
“/bin/bash\r”,而不是“/bin/bash”。 - 系统中当然不存在一个叫
bash^M的程序,所以就会报错 “No such file or directory”。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 wenzi'blog!
