必须强制使用lf(\n)换行符,因shell解释器严格遵循posix标准,仅识别\n为行结束;若含\r(如crlf),\r会被当作命令名一部分,导致“#!/bin/sh^m: no such file or directory”等错误。

如果目标是让生成的 Shell 脚本在所有系统上都使用 LF(\n)换行符,而不是依赖运行环境的 System.lineSeparator()(Windows 下为 \r\n),就不能调用 BufferedWriter.newLine()——因为它会自动适配当前 JVM 所在平台。
直接写入 LF,不走 newLine()
最稳妥的方式是:绕过 newLine(),手动写入 "\n" 字符串,并确保编码正确(UTF-8)、无多余 BOM 或回车符。
- 用
BufferedWriter.write("\n")替代newLine() - 避免拼接
"\r\n"或System.getProperty("line.separator") - 尤其注意:不要在字符串末尾额外加
\r,否则变成\r\n,Linux 下可能报错command not found(因 shebang 行末多了\r)
配套关键设置:编码 + 流包装
Shell 脚本对编码和换行极其敏感。光写 \n 不够,还需保证:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 输出流明确指定 UTF-8 编码:
new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8) - 用
BufferedWriter包装它(不是FileWriter,后者不指定编码,易受系统默认编码影响) - 每行内容末尾只写
"\n",例如:writer.write("#!/bin/sh\n");
验证脚本是否真为 LF
生成后可用命令快速确认:
- Linux/macOS:
file -i script.sh看编码;xxd script.sh | head查首几字节,LF 是0a,CRLF 是0d 0a - Windows(WSL 或 Git Bash):
dos2unix -ic script.sh检查是否含\r - Vim 中输入
:set list,若看到$结尾且无^M,说明是干净 LF
为什么必须强制 LF?
Shell 解释器(如 /bin/sh、/bin/bash)严格遵循 POSIX 标准:只识别 \n 为行结束。遇到 \r\n 时,\r 会被当作普通字符保留在命令名或参数中,导致 ./script.sh: line 1: #!/bin/sh^M: No such file or directory 类错误。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










