解决单引号跟ProcessBuilder在Linux环境下运行命令报错的问题
背景:项目需求需要在Java代码里使用ProcessBuilder调用Linux环境下K8S的命令完整命令为:kubectl --kubeconfig=/home/service/k8s/<ns>.config -n <ns> patch service <service_name> -p '{"spec":{"selector":{"app":"<dep
·
背景:项目需求需要在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小时折磨得到的解决方案
并且我相信我是全网第一个关于该问题的解决方案
更多推荐
已为社区贡献1条内容
所有评论(0)