Termux环境下shell脚本双引号已闭合仍报解析错误如何解决?
错误原因
- 核心问题是shell双引号嵌套解析冲突,出现在脚本最后else分支的代码行:
eval "exec $command login -c "$com""
外层已经用双引号包裹整个eval参数,内层-c后面的$com又直接使用双引号包裹,shell解析时会把-c后面的第一个双引号判定为外层字符串的结束标记,后续的$com和剩余的双引号无法匹配闭合,最终触发EOF引号匹配报错。
- 你观察到的
command+=" -b /system"行提示引号未闭合属于shell解析错误后的回溯误报,根源和该行无关。
修复方案
快速修复(仅解决当前引号错误)
将出错的else分支代码行的内层双引号转义即可,修改后代码如下:
if [ -z "$com" ];then eval "exec $command login" else eval "exec $command login -c \"$com\"" fi
更稳妥的重构方案(避免后续参数解析问题)
原脚本用字符串拼接命令的方式本身存在参数分词、特殊字符解析错误的隐患,推荐改用bash数组存储命令参数,完全避免引号嵌套问题:
- 替换原字符串拼接的
command变量为数组定义:
# 把原来的command="proot"及后续的command+=行全部替换为数组写法 command=(proot) command+=(-r "$basedir/termux-fs") command+=(-b /system) command+=(-b /dev/) command+=(-b /sys/) command+=(-b /etc/) command+=(-b /proc/) command+=(-b /vendor) command+=(-b /data/dalvik-cache/) command+=(-b /property_contexts) if [ -n "$(ls -A "$basedir"/binds)" ]; then for f in "$basedir"/binds/* ;do . "$f" done fi command+=(-w /data/data/com.termux/files/home/) command+=(/data/data/com.termux/files/usr/bin/env -i) command+=(HOME=/data/data/com.termux/files/home) command+=(PATH=/data/data/com.termux/files/usr/bin:/data/data/com.termux/files/usr/bin/applets) command+=(TERM="$TERM") command+=(ANDROID_DATA=/data) command+=(ANDROID_ROOT=/system) command+=(EXTERNAL_STORAGE=/sdcard) command+=(LANG="$LANG") command+=(LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib) command+=(PREFIX=/data/data/com.termux/files/usr) command+=(TMPDIR=/data/data/com.termux/files/usr/tmp) com=("$@")
- 替换最后执行逻辑,不需要eval即可安全执行:
if [ -z "$com" ];then exec "${command[@]}" login else exec "${command[@]}" login -c "${com[*]}" fi
内容的提问来源于stack exchange,提问作者kung
相关产品推荐
相关产品推荐

