如何在Bash脚本中仅当sudo身份验证失败时循环重试?
解决sudo图形前端脚本循环仅在身份验证失败时执行的问题
问题的核心是sudo的退出码无法直接区分「身份验证失败」和「执行的命令出错」——两种情况都可能返回非0值,导致原脚本的循环无法正常终止。
要解决这个问题,我们可以把「身份验证」和「命令执行」拆分成两步:
- 先用
sudo -v专门处理身份验证,它只会在密码错误/验证失败时返回非0,完全不受后续命令的影响 - 验证通过后,再执行目标命令
修改后的脚本如下:
#!/bin/bash # 先检查sudo是否存在 if ! command -v sudo &> /dev/null; then /usr/lib/gtkdialog/box_splash -bg red -fg white -timeout 5 -text "sudo not found!" exit 1 fi # 循环进行身份验证,直到成功 while true; do # 用sudo -v验证身份,密码通过gtkdialog获取 echo "$(/usr/lib/gtkdialog/box_passwd "$USER password" "Enter password" 2>/dev/null)" | sudo -v -S STATUS=$? if [ $STATUS -eq 0 ]; then break # 验证成功,退出循环 elif [ $STATUS -eq 1 ]; then # 验证失败,弹出提示后继续循环 /usr/lib/gtkdialog/box_passwd "$USER password" "Authentication failed! Please retry" 2>/dev/null >/dev/null else # 其他sudo错误,直接退出 exit $STATUS fi done # 身份验证成功后,执行目标命令 sudo "$@"
关键修改点说明:
- 用
sudo -v单独处理验证:sudo -v的作用是更新sudo的时间戳,只会验证用户身份,不会执行任何命令,所以它的退出码只反映验证结果:- 0:验证成功
- 1:密码错误/验证失败
- 其他值:sudo本身的错误(比如配置问题)
- 拆分验证与执行流程:先确保身份验证通过,再执行目标命令,这样命令的退出码不会干扰验证循环
- 优化sudo存在性检查:用
command -v替代原脚本的退出码127判断,更可靠
这样修改后,只有当密码输入错误时才会重新弹出密码框,命令执行失败或不存在时不会重复要求输入密码。
内容的提问来源于stack exchange,提问作者Lakshay Rohila
相关产品推荐
相关产品推荐

