英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论