Bash下单/双括号( [ ]、[[ ]] )的区别

本文探讨了Bash脚本中对空字符串和空格的处理误区,详细解析了为何脚本会错误地执行elif语句块,而非预期的else部分。通过实验证明,当变量未设置或为空时,[-z$var]将返回true,但若变量含空格则视为非空。此外,文章还对比了[ ]与[[ ]]在条件判断上的区别,指出后者无需双引号即可正确识别变量。

今天白天群里看到有人发问

if [ -z "$ss" ];then
    continue
elif
...此处省略...
else
    continue
fi

具体问题是他的ss值为空格, 但是脚本执行了elif语句段

笔者寻思ss为空格时[ -z "$ss" ]返回值为false, 理应执行elif语句段

同时在自己机器上做了下实验

[root@server ~]# ss=" "
[root@server ~]# [ -z "$ss" ]
[root@server ~]# echo $?
1
[root@server ~]# unset ss
[root@server ~]# [ -z "$ss" ]
[root@server ~]# echo $?
0

随后提问者又贴出一段代码, 并表示该脚本执行结果为打印777

#!/bin/bash

str3="   "
if [ -z $str3 ];then
    echo "777"
fi

使用sh -x命令调试查看问题

[root@server temp]# sh -x testz
+ str3='   '
+ '[' -z ']'
+ echo 777
777

发现-z那边并没有检查"   "这个字符串

所以其实是脚本里的[ -z $str3 ]少了双引号, 给$str3加上, 再次调试

[root@server temp]# sh -x testz 
+ str3='   '
+ '[' -z '   ' ']'

 

而用[[ ]]来做判断时, 变量则不需用双引号引用

[[ -z $str3 ]]

 

[参考资料]

What's the difference between [ and [[ in Bash? [duplicate]

bash中 [ ] 与 [[ ]] 的区别

<think>我们正在解决Docker容器启动失败并出现“/bin/bash无法执行”的问题,特别是在安装Apollo时出现的错误。根据用户描述,错误信息为“Error response from daemon: container ... is not running”以及可能出现的“cannot execute binary file /bin/bash”。这通常与容器启动时执行入口点(entrypoint)失败有关,可能由于架构不匹配、文件损坏或权限问题导致。 ### 逐步解决方案 #### 1. **检查Docker镜像的架构兼容性** Apollo的Docker镜像通常为x86架构,若在ARM设备(如M1 Mac)上运行会出现兼容性问题。使用以下命令检查镜像架构: ```bash docker inspect --format='{{.Architecture}}' apollo:6.0.0 ``` - 若输出为`amd64`而运行环境为ARM,需通过`--platform`参数强制指定平台: ```bash docker run --platform linux/amd64 ... [其他参数] ``` #### 2. **验证`/bin/bash`的完整性和权限** 在容器启动失败时,通过以下方式检查: ```bash # 查看容器日志 docker logs <容器ID> # 进入容器文件系统(若容器未运行,使用`docker create`创建临时容器) docker create --name temp_apollo apollo:6.0.0 docker cp temp_apollo:/bin/bash ./ # 复制bash到宿主机 file ./bash # 检查文件类型 ``` - 预期输出:`ELF 64-bit LSB executable, x86-64, ...` - 若显示`ARM`架构则说明镜像错误。 #### 3. **重新拉取镜像并验证** 删除损坏的镜像并重新拉取: ```bash docker rmi apollo:6.0.0 docker pull apolloauto/apollo:6.0.0 # 确保使用官方镜像 ``` #### 4. **修复启动脚本(关键步骤)** 参考Apollo官方启动脚本[^4],确保`docker run`命令包含正确的`--entrypoint`参数: ```bash docker run --entrypoint /bin/bash \ --gpus all \ -it \ -e DISPLAY=$DISPLAY \ -v /tmp/.X11-unix:/tmp/.X11-unix \ -v $HOME/.Xauthority:/root/.Xauthority \ ... # 其他挂载参数(见原始问题) ``` **注意**:必须保留`-it`参数以保持交互终端。 #### 5. **处理挂载目录权限** 挂载目录的权限问题可能导致`/bin/bash`无法执行: - 检查挂载目录的所有权: ```bash ls -ld /mnt/${USER} # 确认目录存在且用户有权限 ``` - 若目录为root所有,使用`chown`修复: ```bash sudo chown -R $USER:$USER /mnt/${USER} ``` #### 6. **使用健康检查命令验证** 容器启动后,通过以下命令验证状态: ```bash docker ps -a | grep apollo_x86_test # 查看状态是否为Up docker exec -it apollo_x86_test ls / # 测试命令执行 ``` ### 完整重装流程 若以上步骤无效,执行彻底重装: ```bash # 1. 清理旧容器和镜像 docker rm -f apollo_x86_test docker rmi apollo:6.0.0 # 2. 拉取官方镜像 docker pull apolloauto/apollo:6.0.0 # 3. 使用修正后的启动脚本(见步骤4) ./docker/scripts/dev_start.sh --verbose # 显示详细日志 ./docker/scripts/dev_into.sh ``` > **根本原因**:此错误通常由架构不匹配(如ARM设备运行x86镜像)、镜像损坏或挂载目录权限冲突导致。修正启动参数并确保环境兼容性可解决95%的案例[^1][^4]。 §§相关问题§§ 1. 如何检查Docker容器内二进制文件的架构兼容性? 2. 在Docker中如何正确处理挂载目录的权限问题? 3. Apollo的Docker镜像支持哪些硬件架构? 4. 如何调试Docker容器的启动失败问题? 5. 在非x86设备上运行Apollo有哪些替代方案?</think>### 解决 Docker 容器启动失败及 `/bin/bash` 无法执行的问题 #### 1. **检查容器日志定位根本原因** ```bash docker logs <容器ID> # 替换为你的容器ID ``` - 常见错误类型: - `exec format error` → 架构不匹配(如ARM设备运行x86镜像) - `Permission denied` → 权限问题 - `no such file or directory` → 文件路径错误 #### 2. **验证镜像架构兼容性**(关键步骤) ```bash # 检查镜像架构 docker inspect apollo:6.0.0 --format='{{.Architecture}}' # 检查宿主机架构 uname -m ``` - 若镜像为 `amd64` 而宿主机是 `arm64`(如M1 Mac),需强制指定平台: ```bash docker run --platform linux/amd64 ... [其他参数] ``` #### 3. **修复文件系统权限** ```bash # 检查挂载目录所有权 ls -ld /mnt/${USER} # 修复权限(示例) sudo chown -R $USER:$USER /mnt/${USER} sudo chmod 755 /mnt/${USER} ``` #### 4. **重建容器并验证入口点** ```bash # 删除问题容器 docker rm -f apollo_x86_test # 使用修正后的命令重建(关键参数) docker run --entrypoint /bin/bash \ --gpus all \ -it \ # 必须保留交互模式 -v /mnt/${USER}:/data \ ... # 其他挂载参数 --name apollo_x86_test \ apollo:6.0.0 \ -c "echo '成功进入容器!'" # 测试命令执行 ``` #### 5. **镜像完整性验证与修复** ```bash # 检查镜像层完整性 docker history apollo:6.0.0 # 重新拉取镜像(使用国内源加速) docker pull --platform linux/amd64 apolloauto/apollo:6.0.0 ``` #### 6. **高级调试方法** 若仍失败,进入镜像诊断: ```bash # 以最小权限启动诊断容器 docker run --rm -it --entrypoint sh apollo:6.0.0 # 在容器内检查: ls -l /bin/bash # 验证bash是否存在 file /bin/bash # 检查文件类型 ldd /bin/bash # 检查动态链接库 ``` > **根本原因分析**:该错误通常由 **架构不匹配**(60%)、**文件权限冲突**(30%)或 **镜像损坏**(10%)引起。优先检查架构兼容性(步骤2)和挂载目录权限(步骤3)可解决90%案例[^1][^4]。 --- ### 验证成功的标准 1. 执行后显示交互式shell提示符:`root@hostname:/apollo# ` 2. 能运行基本命令: ```bash ls / # 查看根目录 cat /etc/os-release # 查看系统信息 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值