如何将Golang变量传递给Bash脚本?现有代码场景下的实现方案
问题描述
用户现有如下script.sh脚本:
#!/bin/sh dbt run --select $model_tag --profiles-dir .
该脚本需要接收来自Go服务代码invoke.go的model_tag变量。invoke.go是一个HTTP服务,核心代码如下:
package main import ( "fmt" "log" "net/http" "os" "os/exec" ) func handler(w http.ResponseWriter, r *http.Request) { log.Print("helloworld: received a request") mt := r.Header.Get("Model-Tag") cmd := exec.CommandContext(r.Context(), "/bin/sh","script.sh") cmd.Stderr = os.Stderr out, err := cmd.Output() if err != nil { w.WriteHeader(500) } w.Write(out) } func main() { log.Print("helloworld: starting server...") http.HandleFunc("/", handler) port := os.Getenv("PORT") if port == "" { port = "8080" } log.Printf("helloworld: listening on %s", port) log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil)) }
在handler函数中,mt是从请求头获取的变量,用户希望将mt赋值给script.sh中的model_tag后执行脚本,但直接设置出现语法错误,需要正确的实现方法。
解决方案
有两种可靠的方式可以实现变量传递,避免语法错误:
方法一:通过环境变量传递
1. 修改script.sh读取环境变量
将脚本中的$model_tag改为读取环境变量(大写是Shell环境变量惯例,也可保持原变量名,只要两边对应即可):
#!/bin/sh dbt run --select "$MODEL_TAG" --profiles-dir .
2. 在Go代码中设置环境变量
创建exec.Cmd后,复制当前进程环境并添加目标变量:
func handler(w http.ResponseWriter, r *http.Request) { log.Print("helloworld: received a request") mt := r.Header.Get("Model-Tag") // 复制原有环境变量,避免覆盖系统默认配置 env := os.Environ() env = append(env, fmt.Sprintf("MODEL_TAG=%s", mt)) cmd := exec.CommandContext(r.Context(), "/bin/sh","script.sh") cmd.Env = env cmd.Stderr = os.Stderr out, err := cmd.Output() if err != nil { w.WriteHeader(500) fmt.Fprintf(w, "执行脚本出错: %v", err) return } w.Write(out) }
这种方式安全性更高,能避免命令注入风险,且无需修改脚本调用方式。
方法二:通过命令行参数传递
1. 修改script.sh接收位置参数
将脚本改为接收第一个命令行参数:
#!/bin/sh # $1表示传入的第一个命令行参数 dbt run --select "$1" --profiles-dir .
2. 在Go代码中传递参数
调用脚本时直接将mt作为参数传入:
func handler(w http.ResponseWriter, r *http.Request) { log.Print("helloworld: received a request") mt := r.Header.Get("Model-Tag") // 将mt作为参数传给script.sh cmd := exec.CommandContext(r.Context(), "/bin/sh","script.sh", mt) cmd.Stderr = os.Stderr out, err := cmd.Output() if err != nil { w.WriteHeader(500) fmt.Fprintf(w, "执行脚本出错: %v", err) return } w.Write(out) }
这种方式直观简洁,适合简单的参数传递场景。
内容的提问来源于stack exchange,提问作者Tanay Maheshwari
相关产品推荐
相关产品推荐

