在 Windows 上编辑的 Bash/Korn shell 脚本会抛出错误“...^M:未找到”

在 Windows 上编辑的 Bash/Korn shell 脚本会抛出错误“...^M:未找到”

我使用 Notepad++ 在 Windows 中编写了一个 Bash 脚本。

cxStopAllServicesOnSERVER.sh

#!/usr/bin/bash
cd "/some/path"
echo "Hi. Logs can be found at "`pwd`"/cxStartStopLogger.log"
echo "["`date`"]*** STOPPING ALL SERVICES ON SERVER ***" >> "cxStartStopLogger.log"
exit

现在上传它并设置所需的文件权限后,我尝试按如下方式执行它:

bash-3.00$ cat cxStopAllServicesOnSERVER.sh #Let's have a look at the code.
#!/usr/bin/bash
cd "/some/path/"
echo "Hi. Logs can be found at "`pwd`"/cxStartStopLogger.log"
echo "["`date`"]*** STOPPING ALL SERVICES ON SERVER ***" >> "cxStartStopLogger.log"

bash-3.00$ # Code and hashbang 'looks' correct, 
bash-3.00$ # if there is any issue with the format (EOL characters and such) 
bash-3.00$ # we cannot see it using cat.
bash-3.00$ 
bash-3.00$ sh cxStopAllServicesOnSERVER.sh
cxStopAllServicesOnSERVER.sh[2]: /some/path^M:  not found
Hi. Logs can be found at /some/path/cxStartStopLogger.log
bash-3.00$ # Note that ^M appears at the end of the line.

bash-3.00$ bash -x cxStopAllServicesOnSERVER.sh
+ cd $'/some/path\r'
: No such file or directory1.sh: line 2: cd: /some/path
++ pwd
' echo 'Hi. Logs can be found at /some/path/cxStartStopLogger.log
Hi. Logs can be found at /some/path/cxStartStopLogger.log
++ date
+ echo '[Sun' Nov 18 00:28:17 EST '2012]*** STOPPING ALL SERVICES ON SERVER ***'
bash-3.00$ # Note that '\r' return character appears at the end of the line.

问题: 当我将代码更改为 korn shell 时,我遇到了同样的问题。似乎在行尾添加了不正确的字符。

笔记: 我找到了解决方案并发布了与答案相同的内容。请随意更新或改进它,以帮助可能面临相同问题的其他初学者。谢谢!

答案1

在浏览了各种论坛和一些 Stack-overflow 帖子后,我发现了这个问题。

以下是为了更好地理解和“查看”错误的根本原因的解释。

首先,如果您在 Windows 上编写代码,最好用 Notepad++ 武装自己。在我看来,它基本上是文本编辑器的瑞士军刀。

现在要查看 EOL(行尾)字符和其他控制符号,请执行以下操作:

1.在Notepad++中打开文件。

从菜单栏中选择视图 > 显示符号 > 显示所有字符

您现在应该看到如下符号: Notepad++ 的屏幕截图:在 Windows 上编辑 UNIX 脚本

啊哈! Windows/MS-DOS 使用 CR+LF 来指示行结束。现在UNIX使用LF字符来指示行终止符(EOL字符)。

2.1.让我们将 Windows EOL 转换为 UNIX EOL:

选择编辑 > EOL 转换 > UNIX 格式

你应该看到这样的东西:

Notepad++ 的屏幕截图:EOL 转换为 UNIX 格式 这解释了为什么我们看到“\r”字符被附加在行尾。这是因为 UNIX 将“\n”或 LF(换行符)识别为行终止/EOL 字符,但忽略“\r”或 ^M(回车)字符。

我们还可以通过以下方式测试 EOL 问题

bash-3.00$ head myScript.sh | cat -vet | head -1
#usr/bin/bash^M$
bash-3.00$ #We see that ^M, that is \r is found at the end of each line. 

2.2.如果您想将文件从 Windows 转换为 UNIX 上的 UNIX EOL 格式,则有两种方法可以解决此问题:

$ dos2unix myScript.sh

或者

使用提供的解决方案@克里斯唐恩如下:

$ sed -i 's/\r$//' myScript.sh

参考:

  1. 欲了解更多信息线路终止r 和 n 之间有什么区别请参考这些链接。

答案2

您的脚本包含 CRLF 行结尾,而 Unix 使用 LF 行结尾。如果您有 GNU sed,以下命令将删除它们:

sed -i 's/\r$//' cxStopAllServicesOnSERVER.sh

如果您没有 GNU sed,请写入临时文件,然后将其移至旧文件的顶部。

顺便说一句,如果您使用 调用脚本sh,您将覆盖 shebang。这可能不是你想要的。

相关内容