如何在Bash中检测/dev/mapper/dev0是否存在?
如何在Bash中检测/dev/mapper/dev0是否存在?
看起来你是在给NAS做自动解密挂载的脚本,遇到了检测LUKS映射设备的问题对吧?我来帮你分析下原因和解决办法:
首先,你用[ -e /dev/mapper/dev0 ]没生效的大概率原因是权限问题——/dev/mapper目录下的设备文件默认只有root用户能访问,普通用户执行这个检测时会因为权限不足,误判为“不存在”,但实际上可能已经创建了。
给你几个更靠谱的解决方案:
方案1:用sudo辅助检测设备文件
既然cryptsetup需要sudo执行,那检测设备文件的时候也加上sudo,就能获取到正确的状态:
if sudo [ -e /dev/mapper/dev0 ]; then # 设备存在的逻辑 echo "true" ssh -i /home/user/.ssh/another-machine novum@10.147.20.100 -t 'play "/images/voices/Shuuten Douji/databasesunlocked.mp3"; wait; exit;' fail="false" else # 设备不存在的逻辑 ssh -i /home/user/.ssh/another-machine novum@10.147.20.100 -t 'play "/images/voices/Shuuten Douji/that was incorrect, but please try again.mp3"; wait; exit;' fi
方案2:直接检查cryptsetup luksOpen的退出状态(更推荐)
其实不用纠结设备文件是否存在,cryptsetup luksOpen执行成功时退出码是0,失败则是非0,直接判断命令的执行结果反而更准确——毕竟有时候设备文件可能存在,但解密过程其实有问题。
你可以修改脚本里的循环部分,记录每个解密命令的状态:
fail="true" LUKS_PASSWORD1="" # 注意这里的语法修正:变量加引号,等号两边留空格 while [ "$fail" = "true" ]; do echo -n " Password > " read LUKS_PASSWORD1 echo ""; all_succeeded=true pids=() # 并行执行解密,记录每个进程PID for dev in "${!devs[@]}"; do echo "Opening ${devs[$dev]} to $dev" echo "$LUKS_PASSWORD1" | sudo cryptsetup luksOpen "$dev" "${devs[$dev]}" -d - & pids+=($!) done; # 等待所有解密进程完成,检查每个的退出状态 for pid in "${pids[@]}"; do wait "$pid" if [ $? -ne 0 ]; then all_succeeded=false fi done if $all_succeeded; then echo "true" ssh -i /home/user/.ssh/another-machine novum@10.147.20.100 -t 'play "/images/voices/Shuuten Douji/databasesunlocked.mp3"; wait; exit;' fail="false" else ssh -i /home/user/.ssh/another-machine novum@10.147.20.100 -t 'play "/images/voices/Shuuten Douji/that was incorrect, but please try again.mp3"; wait; exit;' # 清理已打开的设备,避免残留 for dev in "${!devs[@]}"; do sudo cryptsetup luksClose "${devs[$dev]}" 2>/dev/null done fi done
这里还帮你修正了原脚本里的一个语法错误:while [ $fail="true" ]; do应该改成while [ "$fail" = "true" ]; do,变量要加引号防止空格问题,等号两边必须留空格,否则Bash会把$fail=true当成一个整体字符串,导致循环永远无法退出。
备注:内容来源于stack exchange,提问作者Novum Gain




