cmd.add("bash -c "+BashStringEscapes.wrapBash(command));
/** * Merges the commands and env, into a single set of commands. Also escapes the commands as required. * * Not all ssh servers handle "env", so instead convert env into exported variables */ protected List<String> toCommandSequence(List<String> commands, Map<String,?> env) { List<String> result = new ArrayList<String>((env!=null ? env.size() : 0) + commands.size()); if (env!=null) { for (Entry<String,?> entry : env.entrySet()) { if (entry.getKey() == null || entry.getValue() == null) { LOG.warn("env key-values must not be null; ignoring: key="+entry.getKey()+"; value="+entry.getValue()); continue; } String escapedVal = BashStringEscapes.escapeLiteralForDoubleQuotedBash(entry.getValue().toString()); result.add("export "+entry.getKey()+"=\""+escapedVal+"\""); } } for (CharSequence cmd : commands) { // objects in commands can be groovy GString so can't treat as String here result.add(cmd.toString()); } return result; }
@Test public void testBashEscaping() { Assert.assertEquals( BashStringEscapes.doubleQuoteLiteralsForBash("-Dname=Bob Johnson", "-Dnet.worth=$100"), "\"-Dname=Bob Johnson\" \"-Dnet.worth=\\$100\""); }
MutableList<Object> c2 = MutableList.of(); for (Object ci: c1) { c2.add(StringEscapes.BashStringEscapes.wrapBash((String)ci));
result.add(wrapBash(hostAndPort.getHostText())); Integer whichPort = knifeWhichPort(hostAndPort); if (whichPort!=null) result.add("-p "+whichPort); result.add("-x "+wrapBash(checkNotNull(machine.getUser(), "user"))); result.add("-r "+wrapBash(runList.apply(entity()))); result.add("-j "+wrapBash(new GsonBuilder().create() .toJson(knifeAttributes)));
result.add(wrapBash(hostAndPort.getHostText())); Integer whichPort = knifeWhichPort(hostAndPort); if (whichPort!=null) result.add("-p "+whichPort); result.add("-x "+wrapBash(checkNotNull(machine.getUser(), "user"))); result.add("-r "+wrapBash(runList.apply(entity()))); result.add("-j "+wrapBash(new GsonBuilder().create() .toJson(knifeAttributes)));
/** * Sets all JVM options (-X.. -D..) in an environment var JAVA_OPTS. * <p> * That variable is constructed from {@link #getJavaOpts()}, then wrapped _unescaped_ in double quotes. An * error is thrown if there is an unescaped double quote in the string. All other unescaped * characters are permitted, but unless $var expansion or `command` execution is desired (although * this is not confirmed as supported) the generally caller should escape any such characters, for * example using {@link BashStringEscapes#escapeLiteralForDoubleQuotedBash(String)}. */ @Override public Map<String, String> getShellEnvironment() { List<String> javaOpts = getJavaOpts(); for (String it : javaOpts) { BashStringEscapes.assertValidForDoubleQuotingInBash(it); } // do not double quote here; the env var is double quoted subsequently; // spaces should be preceded by double-quote // (if dbl quotes are needed we could pass on the command-line instead of in an env var) String sJavaOpts = Joiner.on(' ').join(javaOpts); return MutableMap.<String, String>builder().putAll(super.getShellEnvironment()).put("JAVA_OPTS", sJavaOpts).build(); }
public String getArgs(){ List<Object> args = getEntity().getConfig(VanillaJavaApp.ARGS); StringBuilder sb = new StringBuilder(); Iterator<Object> it = args.iterator(); while (it.hasNext()) { Object argO = it.next(); try { String arg = Tasks.resolveValue(argO, String.class, getEntity().getExecutionContext()); BashStringEscapes.assertValidForDoubleQuotingInBash(arg); sb.append(format("\"%s\"",arg)); } catch (Exception e) { throw Exceptions.propagate(e); } if (it.hasNext()) { sb.append(" "); } } return sb.toString(); }
public static String warn(String message) { return "( echo "+BashStringEscapes.wrapBash(message)+" | tee /dev/stderr )"; }
public static boolean isValidForDoubleQuotingInBash(String x) { return (checkValidForDoubleQuotingInBash(x)==null); }
/** fails with nice error if the given file does not exist */ public static String requireExecutable(String command) { return require("which "+BashStringEscapes.wrapBash(command), "The required executable \""+command+"\" does not exist"); }
@Override public Map<String, String> getShellEnvironment() { Map<String, String> shellEnv = MutableMap.<String, String>builder() .putAll(super.getShellEnvironment()) .remove("JAVA_OPTS") .put("CATALINA_PID", "pid.txt") .put("CATALINA_BASE", getRunDir()) .put("RUN", getRunDir()) .build(); // Double quoting of individual JAVA_OPTS entries required due to eval in catalina.sh List<String> javaOpts = getJavaOpts(); String sJavaOpts = BashStringEscapes.doubleQuoteLiteralsForBash(javaOpts.toArray(new String[0])); shellEnv.put("CATALINA_OPTS", sJavaOpts); return shellEnv; }
/** fails with nice error if the given file does not exist */ public static String requireFile(String file) { return requireTest("-f "+BashStringEscapes.wrapBash(file), "The required file \""+file+"\" does not exist"); }
@Override public String apply(String input) { return wrapBash(input); } }
private static String sudoNew(String command) { if (command==null) return null; // on some OS's e.g. Centos 6.5 in SL, sudo -- X tries to run X as a literal argument; // in particular "( echo foo && echo bar )" fails when passed as an argument in that way, // but works if passed to bash -c; // but others e.g. OS X fail if you say sudo -- bash -c "( echo foo )" ... not liking the parentheses // piping to sudo bash seems the most reliable way return "( if test \"$UID\" -eq 0; then ( "+command+" ); else " + "echo " + BashStringEscapes.wrapBash(command) + " | " + "sudo -E -n -S -s -- bash" + " ; fi )"; }
protected String knifeExecutable() { if (knifeExecutable!=null) return knifeExecutable; String knifeExecFromConfig = entityConfig(ChefConfig.KNIFE_EXECUTABLE); if (knifeExecFromConfig!=null) return BashStringEscapes.wrapBash(knifeExecFromConfig); // assume on the path, if executable not set return "knife"; }
@Test public void testBashEscapable() { Assert.assertTrue(BashStringEscapes.isValidForDoubleQuotingInBash("Bob Johnson")); Assert.assertFalse(BashStringEscapes.isValidForDoubleQuotingInBash("\"")); Assert.assertTrue(BashStringEscapes.isValidForDoubleQuotingInBash("\\\"")); }
public static void assertValidForDoubleQuotingInBash(String x) { String problem = checkValidForDoubleQuotingInBash(x); if (problem==null) return; throw new IllegalArgumentException("String \""+x+"\" not acceptable for bash argument (including double quotes): "+problem); }
/** transforms e.g. [ "-Dname=Bob Johnson", "-Dnet.worth=$100" ] to * a java string "\"-Dname=Bob Johnson\" \"-Dnet.worth=\$100\"" -- * which can be inserted into a bash command where it will be picked up as 2 params */ public static String doubleQuoteLiteralsForBash(String... args) { StringBuilder result = new StringBuilder(); for (String arg: args) { if (!Strings.isEmpty(result)) result.append(" "); result.append("\""); result.append(escapeLiteralForDoubleQuotedBash(arg)); result.append("\""); } return result.toString(); }
protected String knifeExecutable() { if (knifeExecutable!=null) return knifeExecutable; String knifeExecFromConfig = entityConfig(ChefConfig.KNIFE_EXECUTABLE); if (knifeExecFromConfig!=null) return BashStringEscapes.wrapBash(knifeExecFromConfig); // assume on the path, if executable not set return "knife"; }