Home >Backend Development >Golang >Execute dynamic bash scripts using Go, including a one-line function declaration

Execute dynamic bash scripts using Go, including a one-line function declaration

WBOY
WBOYforward
2024-02-05 23:09:11851browse

"使用

Question content

I am writing a bash task runner using go, which has a simple concept:

  1. It reads taskfile which is a bash script containing a task definition (a simple bash function declaration)
  2. It adds additional content dynamically
  3. Execute the command according to the passed parameters

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?


Correct Answer


First of all: it doesn’t make any sense 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.

Second: Explain reason

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!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete