Running an Embedded Bash Script With Command-Line Arguments in Go

In this article, we will explore how to embed a Bash script within a Go program and execute it while passing command-line arguments to the embedded script. This approach allows us to package the script directly within the Go binary, eliminating the need for an external script file. We will leverage the os/exec package and the Go embed feature to achieve this.

Prerequisites

  • Basic understanding of Go programming language
  • Familiarity with executing shell scripts

Step 1: Embedding the Bash Script

To embed the Bash script in the Go program, we can use the Go embed feature. Place the Bash script file, named bash.sh in this example, alongside the Go source file. Annotate the script content using the //go:embed directive to indicate that it should be embedded in the binary:

1
2
//go:embed bash.sh
var scriptContent []byte

Step 2: Executing the Embedded Bash Script

Now, let’s execute the embedded Bash script while passing command-line arguments. Here’s the updated code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

import (
 _ "embed"
 "fmt"
 "log"
 "os"
 "os/exec"
 "strings"
)

//go:embed bash.sh
var scriptContent []byte

func main() {
 args := os.Args[1:] // Get the command-line arguments excluding the program name

 cmd := exec.Command("/bin/bash", "-s") // Execute the script directly, without -c flag
 cmd.Stdin = strings.NewReader(string(scriptContent))
 cmd.Stdout = os.Stdout
 cmd.Stderr = os.Stderr

 cmd.Args = append(cmd.Args, args...) // Append the command-line arguments to the command

 err := cmd.Run()
 if err != nil {
  log.Fatalf("Failed to execute bash script: %v", err)
 }

 fmt.Println("Bash script executed successfully.")
}

Explanation

  • We retrieve the command-line arguments using os.Args[1:], excluding the program name.
  • The exec.Command function is used to create the command to execute the Bash script. We pass /bin/bash as the command and -s to indicate that the script will be provided via stdin.
  • We set cmd.Stdin to a strings.Reader that contains the embedded script content. This provides the script input to the bash command.
  • The cmd.Stdout and cmd.Stderr fields are set to the respective os.Stdout and os.Stderr to capture the script’s output and error messages.
  • We append the command-line arguments to cmd.Args to pass them as separate arguments to the command.
  • Finally, we execute the command using cmd.Run() and handle any errors that may occur.

Conclusion

By following the steps outlined in this article, you can embed a Bash script within a Go program and execute it while passing command-line arguments. This approach eliminates the need for an external script file and allows you to distribute a single binary. You can further customize the code to suit your specific needs, such as adding additional error handling or modifying the script content.

Remember to adjust any relative paths used in the script if the working directory differs from the original script’s directory. Experiment with embedding different Bash scripts and explore the possibilities of integrating Bash functionality directly within your Go applications.

0%