“command not found”主因是PATH不含当前目录或缺少执行权限;需chmod +x并用./运行;shebang应优先用#!/usr/bin/env bash;注意等号无空格、避免Windows换行符、子shell不继承变量。

脚本执行时直接报错“command not found”
这通常不是语法问题,而是 PATH 没包含当前目录,或脚本没加执行权限。Linux 默认不把 .(当前目录)加入 PATH,所以不能直接敲 myscript.sh 运行。
- 确认权限:
chmod +x myscript.sh,否则即使有 shebang 也执行不了 - 运行方式优先用
./myscript.sh,而非myscript.sh - 如果用了
#!/bin/bash但系统实际是/usr/bin/bash,可能报错;可用#!/usr/bin/env bash更兼容 - 检查 shebang 行末是否混入 Windows 换行符(
^M),用dos2unix myscript.sh或sed -i 's/\r$//' myscript.sh清理
变量未生效或值为空,但看起来写对了
Bash 中变量赋值等号两侧**不能有空格**,且子 shell 不继承父 shell 变量——这是最常被忽略的根源。
- 错误写法:
FOO = "bar"→ 正确是FOO="bar" - 管道会创建子 shell:
echo "a b" | while read x; do echo $x; done中的$x在循环外不可见;改用while read x; do ...; done 或重定向避免 - 导出变量需显式
export VAR,否则source或.加载的脚本里定义的变量不会传给后续命令 - 引用变量建议统一用
"$VAR",避免空格或通配符引发意外分词
用 set -x 调试却看不懂输出
set -x(或 bash -x script.sh)会打印每条执行前的展开结果,但容易混淆“原始语句”和“实际执行内容”。
- 在脚本开头加
set -x,结尾加set +x控制范围;不要全脚本开启 - 注意引号影响:比如
echo "$HOME/*"和echo $HOME/*展开后完全不同,set -x显示的是后者已 glob 展开的结果 - 调试函数时,
set -x会显示函数名+参数,但不会显示函数内局部变量(除非手动declare -p) - 临时加
echo "DEBUG: var=$VAR"比纯set -x更精准,尤其涉及复杂字符串拼接或条件分支时
if 判断总走错分支,[ ] 和 [[ ]] 混用出问题
[ ] 是 POSIX 兼容的外部命令(常为 /bin/[),而 [[ ]] 是 Bash 内建关键字,行为差异大,混用极易翻车。
-
[ $VAR = "val" ]中若$VAR为空,实际变成[ = "val" ]→ 语法错误;必须写成[ "$VAR" = "val" ] -
[[ $VAR =~ ^[0-9]+$ ]]支持正则,但[ ]不支持;[[ ]]中=~左侧变量无需引号,右侧模式也不能加引号 -
[[ ]]支持==(等价于=)和通配符匹配,[ ]只认=且不支持通配符 - 跨 shell 移植性要求高时用
[ ],但务必加引号;仅 Bash 环境下推荐统一用[[ ]]并关闭set -o nounset配合防御性检查
#!/bin/bash set -euo pipefail # -e:任一命令失败即退出;-u:引用未定义变量报错;-o pipefail:管道中任一环节失败整个管道失败 # 这三者组合能暴露多数隐性错误,比单靠 set -x 更早发现问题
真正卡住的往往不是语法,而是子 shell 边界、变量作用域、以及不同 test 形式对空值/特殊字符的容忍度——这些地方不打日志、不看展开结果,光读代码根本看不出问题。










