You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

执行kubectl exec时出现未终止引号字符串错误的求助

解决kubectl exec执行带引号命令的"Unterminated quoted string"错误

问题概述

通过Shell脚本执行kubectl exec,从YAML文件读取容器名、Pod名、待执行命令和输出文件名,用yq解析YAML。但带引号的命令执行时出现"Unterminated quoted string"错误,直接在命令行运行这些命令正常,存入变量执行则报错,修改引号类型无效。

原脚本函数

get_execs() {
    mkdir ${EXECDIR}
    for con in $(yq '.containers[] | .name' ${YFILE})
    do
        # echo $con
        x=$(i=$con yq '.containers[] | select(.name == env(i)) | .collect_execs[] | .name' ${YFILE})
        # printf \"%s\\n\" \"$x\"
        mkdir ${EXECDIR}/$con
        for j in $x
        do
            c=$(i=$con p=$j yq '.containers[] | select(.name == env(i)) | .collect_execs[] | select(.name == env(p)) | .cmd' ${YFILE})
            pod=$(i=$con yq '.containers[] | select(.name == env(i)) | .pod' ${YFILE})
            # printf \"%s abc\\n\" \"$c\"
            kubectl exec -n ${NAMESPACE} $pod -c $con -- $c > ${EXECDIR}/$con/$j
        done
    done
}

YAML文件结构

containers:
  - name: otg-port-eth1-protocol-engine
    pod: otg-port-eth1
    collect_execs:
    - name: resource-usage
      cmd: top -c -n 2 -b -H -w 120
    - name : disk-space
      cmd : df -H 
    - name: cpu-info
      cmd: cat /proc/cpuinfo
    - name: interface-manager-threads-iter1
      cmd : sh -c 'gdb --eval-command \"set pagination 0\" --eval-command \"thread apply all bt\" --batch --pid $(pidof InterfaceManager)'
    - name: interface-manager-threads-iter2
      cmd : sh -c 'gdb --eval-command \"set pagination 0\" --eval-command \"thread apply all bt\" --batch --pid $(pidof InterfaceManager)'
    - name: interface-manager-shared-sos
      cmd: sh -c 'cat /proc/$(pidof InterfaceManager)/maps'
    - name: netstat
      cmd: netstat -an
    - name: dmesg
      cmd : dmesg
    - name : ifconfig
      cmd : ifconfig

错误信息

--eval-command: 1: Syntax error: Unterminated quoted string
command terminated with exit code 2
--eval-command: 1: Syntax error: Unterminated quoted string
command terminated with exit code 2
/proc/$(pidof: 1: Syntax error: Unterminated quoted string
command terminated with exit code 2
--eval-command: 1: Syntax error: Unterminated quoted string
command terminated with exit code 2
--eval-command: 1: Syntax error: Unterminated quoted string
command terminated with exit code 2
/proc/$(pidof: 1: Syntax error: Unterminated quoted string
command terminated with exit code 2

问题根源

  • 变量展开时引号丢失:带引号的命令存入单个变量后,Shell执行时会拆分参数但不重新解析引号,导致原命令的引号结构被破坏。
  • for循环的空格拆分:for con in $(yq ...)这类写法会将含空格的元素拆分成多个循环项,引发解析错误。
  • YAML转义处理失效:YAML中的\"转义引号在yq输出后,Shell无法正确识别为引号的一部分。

解决方案

步骤1:修改YAML命令为数组格式(推荐)

将复杂带引号命令改为字符串数组,避免转义问题,让Shell能正确识别每个参数:

containers:
  - name: otg-port-eth1-protocol-engine
    pod: otg-port-eth1
    collect_execs:
    - name: resource-usage
      cmd: ["top", "-c", "-n", "2", "-b", "-H", "-w", "120"]
    - name : disk-space
      cmd : ["df", "-H"]
    - name: cpu-info
      cmd: ["cat", "/proc/cpuinfo"]
    - name: interface-manager-threads-iter1
      cmd : ["sh", "-c", "gdb --eval-command \"set pagination 0\" --eval-command \"thread apply all bt\" --batch --pid $(pidof InterfaceManager)"]
    - name: interface-manager-threads-iter2
      cmd : ["sh", "-c", "gdb --eval-command \"set pagination 0\" --eval-command \"thread apply all bt\" --batch --pid $(pidof InterfaceManager)"]
    - name: interface-manager-shared-sos
      cmd: ["sh", "-c", "cat /proc/$(pidof InterfaceManager)/maps"]
    - name: netstat
      cmd: ["netstat", "-an"]
    - name: dmesg
      cmd : ["dmesg"]
    - name : ifconfig
      cmd : ["ifconfig"]

步骤2:修改Shell脚本修复循环与参数传递

get_execs() {
    # 加-p参数避免目录已存在报错
    mkdir -p "${EXECDIR}"
    # 用while read遍历容器名,避免空格拆分
    yq '.containers[] | .name' "${YFILE}" | while read -r con; do
        mkdir -p "${EXECDIR}/${con}"
        # 遍历当前容器的所有collect_execs名称
        yq '.containers[] | select(.name == env(i)) | .collect_execs[] | .name' "${YFILE}" i="${con}" | while read -r j; do
            # 将命令解析为数组
            mapfile -t cmd_arr < <(yq '.containers[] | select(.name == env(i)) | .collect_execs[] | select(.name == env(p)) | .cmd[]' "${YFILE}" i="${con}" p="${j}")
            pod=$(yq '.containers[] | select(.name == env(i)) | .pod' "${YFILE}" i="${con}")
            # 用数组传递参数,保留原命令结构
            kubectl exec -n "${NAMESPACE}" "${pod}" -c "${con}" -- "${cmd_arr[@]}" > "${EXECDIR}/${con}/${j}"
        done
    done
}

关键改进点

  • 用while read -r替代for in $(...),避免空格拆分元素
  • 用mapfile -t将yq输出的命令参数存入数组,保留每个参数的完整性
  • 所有变量用双引号包围,避免空格和特殊字符解析错误
  • YAML命令改为数组格式,让yq直接输出独立参数,无需处理引号转义

备选方案(无需修改YAML)

若无法修改YAML,可使用eval执行命令(仅信任YAML内容时使用,存在注入风险):

# 替换原执行命令的行
eval "kubectl exec -n ${NAMESPACE} ${pod} -c ${con} -- ${c}" > "${EXECDIR}/${con}/${j}"

内容的提问来源于stack exchange,提问作者Alankriti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 10:40:37