解决单引号跟ProcessBuilder在Linux环境下运行命令报错的问题

背景:项目需求需要在Java代码里使用ProcessBuilder调用Linux环境下K8S的命令

完整命令为:
kubectl --kubeconfig=/home/service/k8s/<ns>.config -n <ns> patch service <service_name> -p '{"spec":{"selector":{"app":"<deployment-name>"}}}'

前面是K8S的固定格式,只需要关注最后一段

-p '{"spec":{"selector":{"app":"<deployment-name>"}}}'

解决方案直通车(可以节省观看时间): 那就是将单引号里的内容直接传入,不要拼接单引号!ProcessBuilder会识别为参数自动拼

运行工具方法如下(该方法没任何问题,其他指令正常)

 public static List<String> getRunCmdOutput(String[] command) {
        try {
            Process pro = new ProcessBuilder(command).redirectErrorStream(true).start();
            InputStreamReader isr = new InputStreamReader(pro.getInputStream());
            BufferedReader br = new BufferedReader(isr);
            String str = br.readLine();
            List<String> lineList =new ArrayList<>();
            while (str != null) {
                lineList.add(str);
                System.out.println(str.trim());
                str=br.readLine();
            }
            br.close();
            isr.close();
            pro.waitFor();
            return lineList;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

第一次尝试:单引号直接字符拼接,报错:

第一次尝试报错:Error from server (BadRequest): json: cannot unmarshal string into Go value of type map[string]interface {}

/**
     * 更新k8s的服务的app名
     * kubectl --kubeconfig=/home/service/k8s/<ns>.config -n <ns> patch service <service_name> -p '{"spec":{"selector":{"app":"<deployment-name>"}}}'
     */
    public static void updateK8sServiceName(String ns,String k8sServiceName,String deploymentName){
        String[] updateK8sServiceName={KUBECTL,SDNER_CONFIG_PATH+ns+CONFIG,"-n",ns,"patch","service",k8sServiceName,"-p","'{\"spec\":{\"selector\":{\"app\":\""+deploymentName+"\"}}}'"};
        System.out.println("输入cmd:"+ Arrays.toString(updateK8sServiceName));
        CmdUtil.getRunCmdOutput(updateK8sServiceName);
    }

第二次尝试:转义单引号 (调用代码不再赘述)

转义单引号 \\'  或者\'  
报错: unable to parse "'": yaml: found unexpected end of stream

String[] updateK8sServiceName={KUBECTL,SDNER_CONFIG_PATH+ns+CONFIG,"-n",ns,"patch","service",k8sServiceName,"-p","\\'{\"spec\":{\"selector\":{\"app\":\""+deploymentName+"\"}}}\\'"};

String[] updateK8sServiceName={KUBECTL,SDNER_CONFIG_PATH+ns+CONFIG,"-n",ns,"patch","service",k8sServiceName,"-p","\'{\"spec\":{\"selector\":{\"app\":\""+deploymentName+"\"}}}\ \'"};

第三次尝试:试用空格隔开跟单引号单独字符拼接(用空格隔开用Xshell执行kubectl 是正确的能够执行的)

依旧报错:unable to parse "'": yaml: found unexpected end of stream

String[] updateK8sServiceName={KUBECTL,SDNER_CONFIG_PATH+ns+CONFIG,"-n",ns,"patch","service",k8sServiceName,"-p", "'","{\"spec\":{\"selector\":{\"app\":\"" +deploymentName+"\"}}}","'"};


String[] updateK8sServiceName={KUBECTL,SDNER_CONFIG_PATH+ns+CONFIG,"-n",ns,"patch","service",k8sServiceName,"-p", "'"+"{\"spec\":{\"selector\":{\"app\":\"" +deploymentName+"\"}}}"+"'"};

解决: 在

{"spec":{"selector":{"app":"sdn-web-4321-0wxd"}}} 

这个json两边不需要加’'单引号 ,作为json参数传入时ProcessBuilder会自动为其拼接单引号(用Xshell直接执行不加单引号的报错的)
不加单引号报错
最终执行代码

/**
     * 更新k8s的服务的app名
     * kubectl --kubeconfig=/home/service/k8s/<ns>.config -n <ns> patch service <service_name> -p '{"spec":{"selector":{"app":"<deployment-name>"}}}'
     */
    public static void updateK8sServiceName(String ns,String k8sServiceName,String deploymentName){
        Map<String,Object> map = new HashMap<>();
        Map<String,Object> map2 = new HashMap<>();
        Map<String,Object> map3 = new HashMap<>();
        map3.put("app",deploymentName);
        map2.put("selector",map3);
        map.put("spec", map2);
        JSONObject jsonObject = new JSONObject(map);
        String jsonString = jsonObject.toJSONString();
        // 此处本来jsonString应该包一个单引号的,但是不用包,包了报错,自动会拼一个
        String[] updateK8sServiceName={KUBECTL,SDNER_CONFIG_PATH+ns+CONFIG,"-n",ns,"patch","service",k8sServiceName,"-p", jsonString};
        System.out.println("输入cmd:"+ Arrays.toString(updateK8sServiceName));
        CmdUtil.getRunCmdOutput(updateK8sServiceName);
    }

其实也不需要这个map转json,像之前那样字符拼接也可以的
执行成功
在这里插入图片描述

相信能帮到需要的人,2小时折磨得到的解决方案
并且我相信我是全网第一个关于该问题的解决方案

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值