知用网
白蓝主题五 · 清爽阅读
首页  > 软件入门

shell脚本常见陷阱:新手容易踩的坑

{"title":"shell脚本常见陷阱:新手容易踩的坑","content":"

shell脚本看起来简单,几行命令拼在一起就能跑。但实际用起来,稍不注意就会掉进坑里。尤其是刚上手的时候,有些错误看起来莫名其妙,其实都是老问题换了个马甲。

\n\n

变量没加引号,空格惹的祸

\n

最常见的就是变量赋值和使用时漏了引号。比如:

\n
filename=\"my file.txt\"\nls $filename
\n

看着没问题,但执行时会变成 ls my file.txt,系统当成两个参数处理,直接报“找不到文件”。正确写法是加上双引号:

\n
ls \"$filename\"
\n

这样才把整个变量当一个整体传进去。

\n\n

忘记转义特殊字符

\n

路径里带美元符、反斜杠或者括号,不转义就会出事。比如:

\n
path=\"/home/user/myscript($version)\"\necho $path
\n

这时候shell会尝试解析 $version,哪怕你只是想原样输出。解决办法是该转义就转义:

\n
path=\"/home/user/myscript(\$version)\"
\n\n

== 在 [ ] 里写成 =

\n

在条件判断中,很多人搞混等号的用法。下面这段代码是有问题的:

\n
if [ $name == \"admin\" ]; then\n    echo \"welcome\"\nfi
\n

其实在POSIX标准的 [ ] 里,应该用单个等号。双等号是 [[ ]] 才支持的。稳妥起见,要么统一用单等号,要么改用双中括号。

\n\n

管道后面的变量取不到值

\n

这个特别隐蔽。比如你想统计某个进程数量并判断:

\n
ps aux | grep nginx | wc -l | read count\necho $count
\n

你会发现 $count 是空的。因为管道会创建子shell,read 的赋值在子shell里完成,主shell拿不到。可以用重定向配合 here string 来绕开:

\n
read count <<< $(ps aux | grep nginx | wc -l)\necho $count
\n\n

忽略退出状态码

\n

脚本里执行一条命令失败了,但后面还在继续跑,结果越错越远。默认情况下,shell不会因为某条命令失败就停下来。可以在脚本开头加上:

\n
set -e
\n

这样一旦有命令返回非零状态,脚本立刻退出。更严格的还可以加 set -u(访问未定义变量报错)和 set -o pipefail(管道中任一环节出错也算失败)。

\n\n

shebang写错了位置

\n

第一行必须是 #! 开头,而且得是文件的第一行第一个字符。如果前面不小心加了空行或者注释,脚本可能用默认shell去解释,导致语法错误。尤其在Mac或Windows上编辑过再传到Linux,换行符也可能导致识别失败。

\n\n

用find不加处理空格的保护

\n

遍历文件时直接这么写:

\n
for file in $(find /path -name \"*.log\"); do\n    rm $file\ndone
\n

如果文件名带空格,又没加引号,删的可能就不是你想删的了。更安全的做法是用 while read 配合 -print0

\n
find /path -name \"*.log\" -print0 | while IFS= read -r -d '' file; do\n    rm \"$file\"\ndone
\n\n

这些陷阱每个都不难解决,关键是提前知道它们存在。写脚本别图快,稳一点反而省时间。

","seo_title":"shell脚本常见陷阱:新手最容易忽略的几个坑","seo_description":"详解shell脚本中常见的几个陷阱,包括变量引号缺失、特殊字符未转义、管道子shell问题等,帮助新手避开典型错误。","keywords":"shell脚本,shell陷阱,shell脚本错误,shell调试,shell编程"}