Docker exec执行含expect的GDB脚本失效,请求解决方案
解决方案
问题核心是外层Shell的转义解析干扰:使用docker exec -i $container_id bash -c "..."时,双引号内的转义字符(如\$、括号)会被宿主机Shell提前处理,导致传到容器内的脚本内容被篡改,最终Expect无法正常执行。
以下是两种可行的修复方案:
方案一:修复容器内脚本转义,调整执行命令
- 修正容器内
/opt/gdb_op.sh的转义逻辑,避免Shell提前解析Expect内容:
#!/bin/bash file_path="$1" /usr/bin/expect <<-'EOF' set time 30 spawn gdb - [pidof main] expect "(gdb)" send "set \$len = ((int (*)(char*))getFileLen)(\"'${file_path}'\")\r" send "set \$buf = malloc(\$len)\r" send "set \$file = ((void*(*)(char*, char*))openFile)(\"'${file_path}'\", \"rb\")\r" send "p/x ((int (*)(void*, int, int, void*))readFile)(\$buf, \$len, \$file)\r" send "p/x ((int (*)(void*))closeFile)(\$file)\r" send "detach\r" send "q\r" expect eof EOF
- 将
<<-EOF改为<<-'EOF',关闭Shell对Here Document内变量的解析; - 把
pidof main的反引号替换为Expect原生命令替换语法[pidof main],避免Shell解析。
- 调整Docker执行命令,用单引号包裹固定逻辑,单独拼接变量:
docker exec -i "$container_id" bash -c 'cd /opt;./gdb_op.sh '"$file_path"
- 单引号包裹的部分不会被宿主机Shell解析,变量
$file_path单独拼接保证参数正确传递。
方案二:封装为宿主机脚本,无需容器内预存文件
直接在宿主机编写脚本(如host_gdb_op.sh),整合所有逻辑,无需在容器内放置脚本,更易维护:
#!/bin/bash container_id="$1" file_path="$2" /usr/bin/expect <<-EOF set time 30 spawn docker exec -i $container_id gdb - \$(docker exec $container_id pidof main) expect "(gdb)" send "set \\$len = ((int (*)(char*))getFileLen)(\"$file_path\")\r" send "set \\$buf = malloc(\\\$len)\r" send "set \\$file = ((void*(*)(char*, char*))openFile)(\"$file_path\", \"rb\")\r" send "p/x ((int (*)(void*, int, int, void*))readFile)(\\\$buf, \\\$len, \\\$file)\r" send "p/x ((int (*)(void*))closeFile)(\\\$file)\r" send "detach\r" send "q\r" expect eof EOF
使用方式:
chmod +x host_gdb_op.sh ./host_gdb_op.sh 你的容器ID 目标文件路径
此方案将所有逻辑集中在宿主机,修改维护无需同步文件到容器。
关键注意事项
- 明确转义字符的解析层级:宿主机Shell、容器内Shell、Expect解释器,不同层级需要对应不同的转义方式;
- 单引号可避免Shell解析内部变量和特殊字符,Here Document的单引号模式(
<<-'EOF')可关闭Shell对文档内容的变量解析。
内容的提问来源于stack exchange,提问作者kotoridsk233
相关产品推荐
相关产品推荐

