Home >Backend Development >Golang >Execute dynamic bash scripts using Go, including a one-line function declaration
I am writing a bash task runner using go, which has a simple concept:
taskfile
which is a bash script containing a task definition (a simple bash function declaration)This is a simplified example:
package main import ( "fmt" "os/exec" ) func main() { //simplified for a dynamically built script taskfilecontent := "#!/bin/bash\n\ntask:foo (){\n echo \"test\"\n}\n" // simplified for passed arguments task := "\ntask:foo" bash, _ := exec.lookpath("bash") cmd := exec.command(bash, "-c", "\"$(cat << eof\n"+taskfilecontent+task+"\neof\n)\"") fmt.println(cmd.string()) out, _ := cmd.combinedoutput() fmt.println(string(out)) }
My problem now is that if executed via go it doesn't work and I get this error
task:foo: no such file or directory
But if I execute the generated script directly in the shell, it does work:
$ /opt/opt/homebrew/bin/bash -c "$(cat << EOF #!/bin/bash task:foo (){ echo "test" } task:foo EOF )" test <-- printed out from the `task:foo` above
What am I doing wrong here?
You won't get anything you won't get:
cmd := exec.command(bash, "-c", taskfilecontent+"\n"+task)
If you omit it, your code will be simpler.
When you run in the shell:
65be85239 bed 5...The "
s surrounding $()
are not the syntax of the copy of bash that is starting, but the syntax of the copy of bash that is parsing the command. They are Tells the copy of bash that the result of command substitution will be passed as a string, unaffected by string splitting or wildcards.
Similarly, $(cat <<eof
, eof
and finally )"
is also a command of the interactive shell, rather than what it calls A non-interactive shell. It is an interactive shell that runs cat
(a temporary file containing the contents of a heredoc connected to its standard input), reads a copy of cat
's standard output, and then Replace this data with the single argument passed to bash -c
.
In your go program, you don't have an interactive shell, so you should use go syntax (not shell syntax) to perform all these steps. As far as these steps are concerned, there is no reason to go to the first location (there is no need to write the data file to a temporary file, there is no need to let /bin/cat
read the contents of that file, there is no need to use sub The process runs command substitution to generate a string (consisting of these contents) which is then placed on the command line of the final shell), so it would be wiser to ignore all these steps.
The above is the detailed content of Execute dynamic bash scripts using Go, including a one-line function declaration. For more information, please follow other related articles on the PHP Chinese website!