executeCommandLine
seems to be one of those things that trip up beginners, because people are used to execute a command as a single string that includes the command’s arguments, and it sometimes even includes a redirection or pipe.
Don’t do:
executeCommandLine("/usr/bin/curl -d 'something=\"hello world\"' https://xxx.yyy/zzz")
That won’t work.
The official way
This will work instead:
executeCommandLine("/usr/bin/curl", "-d", "something=\"hello world\"", "https://xxx.yyy/zzz")
In other words, you must split up each argument
of the command, into a separate argument for executeCommandLine
.
Note that you cannot have a pipe / redirection in your command here.
An easier way
A trick is to pass your entire command, even with a pipe / redirection, to your operating system shell.
On Linux/BSD/Mac:
executeCommandLine("/bin/sh", "-c", "/usr/bin/curl -d 'something=\"hello world\"' https://xxx.yyy/zzz | grep 'you can even use pipes!'")
Basically give executeCommandLine 3 arguments:
/bin/sh
- or whatever your shell interpreter is. In Windows it’sC:/Windows/System32/CMD.EXE
(note Java lets you use forward slashes instead of backslashes so you don’t have to escape the backslash with another backslash).-c
on *nix. For Windows use/C
- the full command that you wanted to execute, including all its arguments, as a single string.
Note if your command contains double quotes, you’ll need to escape them with a backslash - depending on your chosen scripting language’s string literal rules.
Additional Notes
There are two versions of executeCommandLine
:
executeCommandLine(command)
: triggers the execution then immediately returns and continues to the next line of code. The command will run independently in the background. The result of the execution is not known in this version.commandOutput = executeCommandLine(Duration, command)
: waits until the command is finished, or the given timeout duration has elapsed, before returning the output of the command as a string. If the command takes longer, it will terminate it.
Duration
is an actual java.time.Duration object.
Examples
RulesDSL
val command = "/usr/bin/curl -d 'something=\"hello world\"' https://xxx.yyy/zzz"
var result = executeCommandLine(Duration.ofSeconds(3), "/bin/sh", "-c", command)
logInfo("Exec Result", result)
JS Scripting
val command = "/usr/bin/curl -d 'something=\"hello world\"' https://xxx.yyy/zzz";
var result = actions.Exec.executeCommandLine(time.Duration.ofSeconds(3), "/bin/sh", "-c", command);
console.log(result);
JRuby
In JRuby, string literals can be expressed with single quotes (not interpolated), double quotes, or with a special % syntax which lets you use a string with both single and double quotes without having to escape it.
command = %(/usr/bin/curl -d 'something="hello world"' https://xxx.yyy/zzz)
result = Exec.execute_command_line(3.seconds, "/bin/sh", "-c", command)
logger.info(result)
JRuby also supports other ways to run a command similar to shell scripting, e.g. using backticks:
result = `/usr/bin/curl -d 'something="hello world"' https://xxx.yyy/zzz`
logger.info(result)