为什么一个正确的shell脚本会给出一个包装/截断/损坏的错误信息?

我有一个似乎应该工作的命令的shell脚本,但相反,它失败了一个奇怪的包装/截断/损坏的错误消息。 例:

$ ls -l myfile -rw-r----- 1 me me 0 Aug 7 12:36 myfile $ cat myscript ls -l myfile $ bash myscript : No such file or directory 

该文件显然存在,但即使我没有,这是我通常会得到的错误消息:

 $ ls -l idontexist ls: cannot access idontexist: No such file or directory 

注意它是如何包含工具名称ls ,消息string和文件名,而我的没有。

这是我得到的,如果我尝试使用mysql 。 错误消息看起来像是已经被包装了,现在开始报价:

 Command: mysql -h myhost.example.com Expected: ERROR 2005 (HY000): Unknown MySQL server host 'myhost.example.com' (0) Actual: ' (0) 2005 (HY000): Unknown MySQL server host 'myhost.example.com 

这里是我应该工作,或者至less给出一个正常的错误信息,而是包装开始冒号和奇怪的破坏结束我的琐碎的SSH命令:

 Command: ssh myhost Expected: ssh: Could not resolve hostname myhost: Name or service not known Actual: : Name or service not knownname myhost 

为什么会发生这种情况,我该如何解决?

TL; DR:您的脚本或数据具有Windows样式的CRLF行尾。

通过删除回车符转换为Unix样式。


如何检查我的脚本或数据是否有回车?

它们在cat -v yourscript的输出中可检测为^M

 $ cat -v myscript ls -l myfile^M 

如果你的脚本没有它们,你的数据可能会 – 特别是从ini / csv文件读取或curl

 hostname=$(curl https://example.com/loginhost.txt) ssh "$hostname" # Shows strange error echo "$hostname" | cat -v # Shows myhost^M 

我如何删除它们?

设置你的编辑器来保存Unix行结尾的文件,也就是“行结束符”或者“行结束符”,然后重新保存。

您也可以使用dos2unix yourscriptcat yourscript | tr -d '\r' > fixedscript从命令行删除它们 cat yourscript | tr -d '\r' > fixedscript

如果在您的数据中find,则可以通过tr -d '\r'您的源代码:

 hostname=$(curl https://example.com/loginhost.txt | tr -d '\r') 

为什么回车会导致奇怪的错误信息?

“回车”字符(又名CR或\r )使光标移动到行的开头,并从那里继续打印。 换句话说,它从头开始覆盖这条线。 这就是为什么他们怪异地换行:

 Intended: ssh: Could not resolve hostname myhost\r: Name or service not known Written: ssh: Could not resolve hostname myhost\r Overwritten: : Name or service not known ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Result: : Name or service not knownname myhost