公司在open-falcon项目的agent模块提供了一个方法,方法里的主要逻辑是通过内置的sys.CmdOutByte
s函数,调用linux的sh -c
命令。
http.HandleFunc("/run", func(w http.ResponseWriter, r *http.Request) {
if r.ContentLength == 0 {
http.Error(w, "body is blank", http.StatusBadRequest)
return
}
bs, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
body := string(bs)
log.Printf("...body..." + body)
//调用linux的sh -c命令
out, err := sys.CmdOutBytes("sh", "-c", body)
if err != nil {
w.Write([]byte("exec fail: " + err.Error()))
return
}
w.Write(out)
})
参数经过外部传入后,在方法变成string类型(即body变量),交给sh -c
执行。
比如,传入的是echo '123'
,那么经过方法处理后变为sh -c "echo '123'"
;
传入的是一个/app/test/test.sh
文件,那么经过方法处理后变为sh -c "/app/test/test.sh"
。
项目中某逻辑是agent接口,传入参数的是/app/open-falcon/plugin/filebeat/filebeat.sh
。
根据上述分析可知,经过方法处理后变为sh -c "/app/open-falcon/plugin/filebeat/filebeat.sh"
。
该sh文件里包含一段解压tar包的命令,如下
tar -zxf /app/open-falcon/plugin/filebeat/filebeat-7.11.1.tar.gz
正常来说,在执行后,在/app/open-falcon/plugin/filebeat
路径下,应该可以看到解压的目录。然而实际在执行后, 无法找到解压的tar目录。
- 机器手动执行
通过xshell进入到该机器的/app/open-falcon/plugin/filebeat
路径,手动执行
sh -c "/app/open-falcon/plugin/filebeat/filebeat.sh"
脚本正常执行,且gz文件正常解压,说明脚本是没问题的。
为什么手动执行没问题呢?难道是通过agent接口执行时,会有环境变量的问题?
- source环境变量
在sh的前面加上
source /etc/profile
echo $(which tar)
通过打印,发现环境变量没问题。
难道是解压到其他目录了?
- find寻找文件
经过find / -name *filebeat*
寻找,发现在/app/open-falcon
里有通过sh脚本解压好的目录。
奇怪,为什么会在这个路径呢?而不是/app/open-falcon/plugin/filebeat
?
因为在/app/open-falcon
路径才有open-falcon的二进制执行文件,所以agent接口调用sys.CmdOutBytes("sh", "-c", body)
时,其所在的路径为/app/open-falcon
。
而我们sh脚本里没有指定解压到哪个目录,所以最终解压的目录所在路径就为/app/open-falcon
sh脚本改为
tar -zxf /app/open-falcon/plugin/filebeat/filebeat-7.11.1.tar.gz -C /app/open-falcon/plugin/filebeat