Better support for running external commands

,

Calling external commands is very common in general. Here, I was just showing a case that specifying the program explicitly does not help.

If your question is about the exact application of this, you would do this when you want to run a command outside of your current session. For example, I used external Julia processes in SnoopCompileBot to snoop the compilation of programs.

About your solution, what if you could not escape the strings manually? Taking your solution with @Tamas_Papp’s suggestion:

julia> ex= raw"""using Printf; @printf("%f",1)"""
"using Printf; @printf(\"%f\",1)"

julia> bashit(str) = run(`bash -c $str`);

julia>  bashit("julia -e $ex")
/bin/bash: -c: line 0: syntax error near unexpected token `"%f",1'
/bin/bash: -c: line 0: `julia -e using Printf; @printf("%f",1)'
ERROR: failed process: Process(`bash -c 'julia -e using Printf; @printf("%f",1)'`, ProcessExited(1)) [1]

Stacktrace:
 [1] pipeline_error at .\process.jl:525 [inlined]
 [2] run(::Cmd; wait::Bool) at .\process.jl:440
 [3] run at .\process.jl:438 [inlined]
 [4] bashit(::String) at .\REPL[12]:1
 [5] top-level scope at REPL[13]:1

julia> bashit("julia -e '$ex'")
/bin/bash: julia: command not found
ERROR: failed process: Process(`bash -c "julia -e 'using Printf; @printf(\"%f\",1)'"`, ProcessExited(127)) [127]

Stacktrace:
 [1] pipeline_error at .\process.jl:525 [inlined]
 [2] run(::Cmd; wait::Bool) at .\process.jl:440
 [3] run at .\process.jl:438 [inlined]
 [4] bashit(::String) at .\REPL[2]:1
 [5] top-level scope at REPL[3]:1

Try cmd:

julia> run(`cmd /c 'julia -e $ex'`)
ERROR: syntax: "$" expression outside quote
Stacktrace:
 [1] top-level scope at none:1
ERROR: failed process: Process(`cmd /c 'julia -e $ex'`, ProcessExited(1)) [1]

Stacktrace:
 [1] pipeline_error at .\process.jl:525 [inlined]
 [2] run(::Cmd; wait::Bool) at .\process.jl:440
 [3] run(::Cmd) at .\process.jl:438

julia> run(`cmd /c "julia -e $ex"`)
ERROR: syntax: incomplete: premature end of input
Stacktrace:
 [1] top-level scope at none:1
ERROR: failed process: Process(`cmd /c 'julia -e using Printf; @printf("%f",1)'`, ProcessExited(1)) [1]

Stacktrace:
 [1] pipeline_error at .\process.jl:525 [inlined]
 [2] run(::Cmd; wait::Bool) at .\process.jl:440
 [3] run(::Cmd) at .\process.jl:438
 [4] top-level scope at REPL[3]:1

Trying some Nodejs code:

julia>  ex= raw"""node -e 'console.log("x")' """
"node -e 'console.log(\"x\")' "

using bashit

julia> bashit(str) = run(`bash -c $ex`);

julia> bashit(ex)
/bin/bash: node: command not found
ERROR: failed process: Process(`bash -c "node -e 'console.log(\"x\")' "`, ProcessExited(127)) [127]

Stacktrace:
 [1] pipeline_error at .\process.jl:525 [inlined]
 [2] run(::Cmd; wait::Bool) at .\process.jl:440
 [3] run at .\process.jl:438 [inlined]
 [4] bashit(::String) at .\REPL[13]:1
 [5] top-level scope at REPL[14]:1


julia> run(`node -v`) # but node is there
v14.7.0
Process(`node -v`, ProcessExited(0))

Try cmd

julia> run(`cmd /c "$ex"`) # x is not printed
Process(`cmd /c "node -e 'console.log(\"x\")' "`, ProcessExited(0))

The point is that for each situation a different workaround is required and. Keeping track of these in a real world application, which you need to run multiple external commands, this becomes frustrating.

1 Like