将bash脚本嵌入二进制文件中的Go代码。

huangapple go评论81阅读模式
英文:

Go: embed bash script in binary

问题

我正在尝试交叉编译一个Go程序,该程序将执行一个bash脚本。是否可以将bash脚本嵌入到二进制文件中?

我参考了以下链接:
https://stackoverflow.com/questions/21595295/golang-serve-static-files-from-memory

不确定这是否适用于执行bash脚本。我是否遗漏了什么?一些澄清或指导将非常有帮助,谢谢!

英文:

I'm trying to cross compile a Go program that will execute a bash script. Is it possible to embed the bash script in the binary?

I've referenced:
https://stackoverflow.com/questions/21595295/golang-serve-static-files-from-memory

Not sure if this applies to executing bash scripts though. Am I missing something here? Some clarification or pointers will be very helpful, thanks!

答案1

得分: 7

由于bash可以从stdin执行脚本,您只需通过command.Stdin将脚本发送给bash命令即可。

一个没有使用go embed的示例:

package main

import (
	"bytes"
	"fmt"
	"os/exec"
	"strings"
)

var script = `
echo $PWD
pwd
echo "-----------------------------------"
# print process
ps aux | grep code
`

func main() {
	c := exec.Command("bash")
	c.Stdin = strings.NewReader(script)

	b, e := c.Output()
	if e != nil {
		fmt.Println(e)
	}
	fmt.Println(string(b))
}

使用go 1.16的embed(https://golang.org/pkg/embed/):

package main

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

//go:embed script.sh
var script string

func main() {
	c := exec.Command("bash")
	c.Stdin = strings.NewReader(script)

	b, e := c.Output()
	if e != nil {
		fmt.Println(e)
	}
	fmt.Println(string(b))
}

附加内容

使用-s -将参数传递给您的脚本。

以下示例将-la /etc传递给脚本。

package main

import (
	"fmt"
	"os/exec"
	"strings"
)

func main() {
	// 以安全的方式将参数传递给您的脚本。
	c := exec.Command("sh", "-s", "-", "-la", "/etc")

	// 像往常一样使用$1,$2,... $@。
	c.Stdin = strings.NewReader(`
	echo $@
	ls $1 "$2"
	`)

	b, e := c.Output()
	if e != nil {
		fmt.Println(e)
	}
	fmt.Println(string(b))
}

Playground: https://go.dev/play/p/T1lMSrXcOIL

英文:

Since bash can execute scripts from stdin, you just send your script to the bash command via command.Stdin.

An example without go embed:

package main

import (
	"bytes"
	"fmt"
	"os/exec"
	"strings"
)

var script = `
echo $PWD
pwd
echo "-----------------------------------"
# print process
ps aux | grep code
`

func main() {
	c := exec.Command("bash")
	c.Stdin = strings.NewReader(script)

	b, e := c.Output()
	if e != nil {
		fmt.Println(e)
	}
	fmt.Println(string(b))
}

With go 1.16 embed (https://golang.org/pkg/embed/):

package main

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

//go:embed script.sh
var script string

func main() {
	c := exec.Command("bash")
	c.Stdin = strings.NewReader(script)

	b, e := c.Output()
	if e != nil {
		fmt.Println(e)
	}
	fmt.Println(string(b))
}

Bonus

Passing parameters to your script with -s -.

The following example will pass -la /etc to the script.

package main

import (
	"fmt"
	"os/exec"
	"strings"
)

func main() {
	// pass parameters to your script as a safe way.
	c := exec.Command("sh", "-s", "-", "-la", "/etc")

	// use $1, $2, ... $@ as usual
	c.Stdin = strings.NewReader(`
	echo $@
	ls $1 "$2"
	`)

	b, e := c.Output()
	if e != nil {
		fmt.Println(e)
	}
	fmt.Println(string(b))
}

Playground: https://go.dev/play/p/T1lMSrXcOIL

答案2

得分: 0

你实际上可以直接在Go中与系统shell进行交互。根据你的bash脚本内容,你可能可以完全将所有内容转换为Go。例如处理文件、提取归档文件、输出文本、请求用户输入、下载文件等等,都可以在Go中本地完成。对于你绝对需要使用shell的任何事情,你总是可以使用golang.org/pkg/os/exec

我写了一个示例代码片段,演示了一个非常简单的基于Go的命令shell。基本上它在用户和shell之间传输输入、输出和错误。它可以用于交互式使用,也可以直接运行大多数shell命令。我在这里提到它主要是为了展示Go的操作系统功能。你可以在这里查看它:github.com/lee8oi/goshell.go

英文:

You can actually directly interface with the system shell in Go. Depending on what's in your bash script you can probably convert everything completely to go. For example things like handling files, extracting archives, outputting text, asking for user input, downloading files, and so much more can be done natively in Go. For anything you absolutely need the shell for you can always use golang.org/pkg/os/exec.

I wrote a snippet that demonstrates a really simple Go based command shell. Basically it pipes input, output, and error between the user and the shell. It can be used interactively or to directly run most shell commands. I'm mentioning it here mostly to demonstrate Go's OS capabilities. Check it out: github.com/lee8oi/goshell.go

答案3

得分: -1

你是否尝试将流数据(根据go-bindata提供的参考文档,它提供了一个返回[]byte的函数)写入临时文件?

参考链接:http://golang.org/pkg/io/ioutil/#TempFile

然后,你可以使用syscall来执行它。

参考链接:http://golang.org/pkg/syscall/#Exec

其中第一个参数需要是一个shell。

英文:

Did you try writing the stream-data (according to the reference go-bindata provides a function that returns []byte) into a temporary file?

see: http://golang.org/pkg/io/ioutil/#TempFile

you can then execute it with a syscall

http://golang.org/pkg/syscall/#Exec

where the first argument needs to be a shell.

huangapple
  • 本文由 发表于 2015年1月5日 20:59:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/27780078.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定