本文记录写新手在 shell 脚本的过程中经常遇到的报错与逃坑方案。
常见报错
这里列举一些新手经常遇到的报错。
$’\r’: command not found或$’\r’: 未找到命令
原因
用 Windows 的同学,经常会遇到这个问题,比如我,习惯性在桌面新建 .txt
文件,更改后缀名为 .sh
,然后用 notepad++ 进行打开。这是由于 Windows 与 Unix 下换行符的差异导致的,Windows 默认新建 .txt
的文件格式为 dos 文件格式,Windows 下换行符其实为”\CR\LF”,Unix 下换行符为”\CR”。
解决方法
方法一: notepad++ 打开脚本,右键 notepad++ 右下角的 Windows(CR LF) 修改为 Unix 保存即可。这里最好在 notepad++ 中选择 设置-首选项-新建的”格式”中选择”Unix(LF)”。
方法二: 使用 dos2unix 转换格式1
2yum install dos2unix # CentOS
apt-get install dos2unix # Ubuntu
执行:1
dos2unix filename
即可。
[-d: command not found或[-d: 未找到命令
出现这个报错一般是部分新手不知道 if 语句两边的中括号要加空格。如下列代码:1
2
3
4!/bin/sh
if [-d /etc]; then
echo "ok"
fi
就会出现这个报错。 改成如下即可:1
2
3
4!/bin/sh
if [空格-d /etc空格]; then
echo "ok"
fi
[:badinterpreter:Nosuchfileordirectory]
这是因为在 Windows 下编辑,传到 Linux 下执行,由于编码不一致,导致的:
在 DOS/windows 里,文本文件的换行符为 rn
,而在 nix
系统里则为n
,所以DOS/Windows
里编辑过的文本文件到了 nix
里,每一行都多了个 ^M
。
解决方法:
1 | vi:%s/r//g:%s/^M//g # (^M输入用Ctrl+v,Ctrl+m) |
引用变量时,变量中的’*’字符被解释器运行了
先看范例:1
2JAVA_OPTIONS='-Dspring.session.redis.cleanup-cron="0 * * * * ?"'
echo $JAVA_OPTIONS
执行该脚本时,结果为:1
-Dspring.session.redis.cleanup-cron="0 1.sh mysql.socket tmpfile
后面的 ‘‘ 变成了脚本目录下的文件名,即 ‘‘ 被解释器运行了。
要避免这种情况只需要在引用变量的时候,用双引号包裹变量即可:1
2JAVA_OPTIONS='-Dspring.session.redis.cleanup-cron="0 * * * * ?"'
echo "$JAVA_OPTIONS"
执行后结果为:1
-Dspring.session.redis.cleanup-cron="0 * * * * ?"
达到预期的效果。
Tips
脚本检验
脚本在运行前最好检查一下语法错误:1
2sh -n filename # 不运行脚本,只检查语法错误
sh -x filename # 运行并跟踪脚本执行过程
这里也可以在脚本的开头加入 set -x
来达到与上述 sh -x
同样的效果。
关于这方面详细可以参考 shell脚本——调试(-n / -x /-c)
ShellCheck 工具
ShellCheck 是一款 shell 脚本静态检查工具,帮助查出错误,同时也会给出一些建议。