Shell脚本执行报错‘bad number’,请求排查问题原因
问题:Ksh脚本执行时出现"bad number"错误,如何修正?
问题描述
我写了一段ksh脚本nexus.ksh,用来通过ldapsearch查询指定ACL组里是否存在某个用户,脚本内容如下:
bash-3.2$ cat nexus.ksh #!/usr/bin/ksh LSEARCH=$(ldapsearch -p 389 -x -D "cn=xx" -w xxxx -b "ou=access,ou=nexus,ou=applications,o=xxx,c=xx" cn=$1 | grep -i uid=$2) echo ldap search output is "${LSEARCH}" if [ "$LSEARCH" -eq " " ]; then echo " User is not present in ACL group...Adding User to ACL group" else echo "User is present in ACL Group" fi
执行后得到的输出里有错误:
bash-3.2$ ./nexus.ksh acl.LINK_ODI_1 xxxx ldap search output is uniquemember: uid=xxx,ou=people,ou=access,ou=nexus,ou=applications,o=xxxx,c= ./nexus.ksh[4]: uniquemember: uid=xxx,ou=people,ou=access,ou=nexus,ou=applications,o=xxx,c=: bad number User is present in ACL Group
请问这段脚本的错误出在哪里?
错误分析与解决方案
核心错误原因
你看到的bad number错误,是因为用了数值比较运算符-eq去处理字符串内容:
- 在
if [ "$LSEARCH" -eq " " ]这一行,-eq是shell专门用来比较两个数字是否相等的运算符。 - 但
$LSEARCH存储的是ldap返回的字符串(比如uniquemember: uid=xxx...),ksh会尝试把这个字符串转换成数字,显然转换失败,所以抛出"bad number"错误。 - 另外,你判断空值的逻辑也不对:
" "是一个包含空格的字符串,而你真正要判断的是$LSEARCH是否为空(也就是ldap没找到匹配用户的情况)。
修正后的脚本
#!/usr/bin/ksh # 给grep的匹配串加引号,避免特殊字符导致问题 LSEARCH=$(ldapsearch -p 389 -x -D "cn=xx" -w xxxx -b "ou=access,ou=nexus,ou=applications,o=xxx,c=xx" cn=$1 | grep -i "uid=$2") echo "ldap search output is '${LSEARCH}'" # 使用-z检查字符串是否为空(无匹配结果时为空) if [ -z "$LSEARCH" ]; then echo "User is not present in ACL group...Adding User to ACL group" else echo "User is present in ACL Group" fi
关键修改点说明
- 替换比较运算符:把
-eq " "换成-z "$LSEARCH",-z是shell标准的空字符串检查运算符,当变量内容为空(长度为0)时条件成立,正好对应ldap没找到用户的场景。 - 给grep匹配串加引号:
grep -i "uid=$2",避免当$2包含特殊字符(比如括号、星号)时,grep把它当成正则表达式的一部分而出错。 - 优化输出可读性:给
${LSEARCH}包裹单引号,方便你直观看到变量是否为空。
额外优化建议(更简洁高效)
你可以直接用grep -q静默检查匹配结果,不需要把结果存储到变量里,这样脚本更简洁,也节省内存:
#!/usr/bin/ksh # grep -q 静默执行,只返回退出码(0=找到匹配,非0=未找到) if ldapsearch -p 389 -x -D "cn=xx" -w xxxx -b "ou=access,ou=nexus,ou=applications,o=xxx,c=xx" cn=$1 | grep -qi "uid=$2"; then echo "User is present in ACL Group" else echo "User is not present in ACL group...Adding User to ACL group" fi
grep -q会关闭输出,只通过退出码告诉脚本是否找到匹配,这样可以直接把整个管道命令放到if条件里,省去变量赋值的步骤。
内容的提问来源于stack exchange,提问作者avi
相关产品推荐
相关产品推荐

