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

WBOY
Release: 2024-02-05 23:09:11
forward
820 people have browsed it

"使用

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))
}
Copy after login

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
Copy after login

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
Copy after login

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)
Copy after login

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!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!