版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Go语言中用 os/exec 执行命令的五种姿势在 Golang 中用于执行命令的库是os/exec,exec.Command 函数返回一个Cmd对象,根据不同的需求,可以将命令的执行分为三种情况1. 只执行命令,不获取结果2. 执行命令,并获取结果(不区分 stdout 和 stderr)3. 执行命令,并获取结果(区分 stdout 和 stderr)第一种:只执行命令,不获取结果直接调用 Cmd 对象的 Run 函数,返回的只有成功和失败,获取不到任何输出的结果。package mainimport ( log os/exec)func main() cmd := exec.Comman
2、d(ls, -l, /var/log/) err := cmd.Run() if err != nil log.Fatalf(cmd.Run() failed with %sn, err) 第二种:执行命令,并获取结果有时候我们执行一个命令就是想要获取输出结果,此时你可以调用 Cmd 的 CombinedOutput 函数。package mainimport (fmtlogos/exec)func main() cmd := exec.Command(ls, -l, /var/log/) out, err := cmd.CombinedOutput() if err != nil fmt.P
3、rintf(combined out:n%sn, string(out) log.Fatalf(cmd.Run() failed with %sn, err) fmt.Printf(combined out:n%sn, string(out)CombinedOutput 函数,只返回 out,并不区分 stdout 和 stderr。如果你想区分他们,可以直接看第三种方法。$ go run demo.go combined out:total 11540876-rw-r-r- 2 root root 4096 Oct 29 2018 yum.logdrwx- 2 root root 94 No
4、v 6 05:56 audit-rw-r-r- 1 root root 185249234 Nov 28 2019 message-rw-r-r- 2 root root 16374 Aug 28 10:13 boot.log不过在那之前,我却发现一个小问题:有时候,shell 命令能执行,并不代码 exec 也能执行。比如我只想查看/var/log/目录下的 log 后缀名的文件呢?有点 Linux 基础的同学,都会用这个命令$ ls -l /var/log/*.logtotal 11540-rw-r-r- 2 root root 4096 Oct 29 2018 /var/log/yum.
5、log-rw-r-r- 2 root root 16374 Aug 28 10:13 /var/log/boot.log按照这个写法将它放入到exec.Commandpackage mainimport (fmtlogos/exec)func main() cmd := exec.Command(ls, -l, /var/log/*.log) out, err := cmd.CombinedOutput() if err != nil fmt.Printf(combined out:n%sn, string(out) log.Fatalf(cmd.Run() failed with %sn,
6、err) fmt.Printf(combined out:n%sn, string(out)什么情况?居然不行,报错了。$ go run demo.go combined out:ls: cannot access /var/log/*.log: No such file or directory2020/11/11 19:46:00 cmd.Run() failed with exit status 2exit status 1为什么会报错呢?shell 明明没有问题啊其实很简单,原来ls -l /var/log/*.log并不等价于下面这段代码。exec.Command(ls, -l, /
7、var/log/*.log)上面这段代码对应的 Shell 命令应该是下面这样,如果你这样子写,ls 就会把参数里的内容当成具体的文件名,而忽略通配符*$ ls -l /var/log/*.logls: cannot access /var/log/*.log: No such file or directory第三种:执行命令,并区分stdout 和 stderr上面的写法,无法实现区分标准输出和标准错误,只要换成下面种写法,就可以实现。package mainimport ( bytes fmt log os/exec)func main() cmd := exec.Command(ls,
8、 -l, /var/log/*.log) var stdout, stderr bytes.Buffer cmd.Stdout = &stdout / 标准输出 cmd.Stderr = &stderr / 标准错误 err := cmd.Run() outStr, errStr := string(stdout.Bytes(), string(stderr.Bytes() fmt.Printf(out:n%snerr:n%sn, outStr, errStr) if err != nil log.Fatalf(cmd.Run() failed with %sn, err) 输出如下,可以看到
9、前面的报错内容被归入到标准错误里$ go run demo.go out:err:ls: cannot access /var/log/*.log: No such file or directory2020/11/11 19:59:31 cmd.Run() failed with exit status 2exit status 1第四种:多条命令组合,请使用管道将上一条命令的执行输出结果,做为下一条命令的参数。在 Shell 中可以使用管道符|来实现。比如下面这条命令,统计了 message 日志中 ERROR 日志的数量。$ grep ERROR /var/log/messages |
10、wc -l19类似的,在 Golang 中也有类似的实现。package mainimport ( os os/exec)func main() c1 := exec.Command(grep, ERROR, /var/log/messages) c2 := exec.Command(wc, -l) c2.Stdin, _ = c1.StdoutPipe() c2.Stdout = os.Stdout _ = c2.Start() _ = c1.Run() _ = c2.Wait()输出如下$ go run demo.go 19第五种:设置命令级别的环境变量使用 os 库的 Setenv 函数
11、来设置的环境变量,是作用于整个进程的生命周期的。package mainimport ( fmt log os os/exec)func main() os.Setenv(NAME, wangbm) cmd := exec.Command(echo, os.ExpandEnv($NAME) out, err := cmd.CombinedOutput() if err != nil log.Fatalf(cmd.Run() failed with %sn, err) fmt.Printf(%s, out)只要在这个进程里,NAME这个变量的值都会是wangbm,无论你执行多少次命令$ go r
12、un demo.go wangbm如果想把环境变量的作用范围再缩小到命令级别,也是有办法的。为了方便验证,我新建个 sh 脚本,内容如下$ cat /home/wangbm/demo.shecho $NAME$ bash /home/wangbm/demo.sh # 由于全局环境变量中没有 NAME,所以无输出另外,demo.go 里的代码如下package mainimport ( fmt os os/exec)func ChangeYourCmdEnvironment(cmd * exec.Cmd) error env := os.Environ() cmdEnv := string for _, e := range env cmdEnv = append(cmdEnv, e) cmdEnv = append(cmdEnv, NAME=wangbm) cmd.Env = cmdEnv return nilfunc main() cmd1 := exec.Command(bash, /home/wangbm/demo.sh) ChangeYourCmdEnvironment(cmd1) / 添加环境变量到 cmd1 命令: NAME=wangbm out1, _ := cmd1.CombinedOutput() fmt.Pri
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 骨关节感染抗菌药物经验治疗
- 化工入门知识课件
- 钢结构组装技术操作要领
- 2026年人力资源管理师薪酬调查技术知识练习(含答案解析)
- 2026云南文山州教育体育局所属事业单位选调37人(2026年第1号)参考考试题库及答案解析
- 2026大理大学招聘硕士及以上人员10人备考考试题库及答案解析
- 2026新东方大学生学习与发展中心云南中心招聘备考考试题库及答案解析
- 立体花墙施工方案(3篇)
- 公路隧洞施工方案(3篇)
- 紫藤花园施工方案(3篇)
- 交通事故培训
- 2026年医保药品目录调整
- 2026四川雅安市汉源县审计局招聘编外专业技术人员2人笔试备考试题及答案解析
- 食品销售业务员培训课件
- 2026年学校意识形态工作计划
- 2025年银行信息科技岗笔试真题及答案
- 山西电化学储能项目建议书
- GB/T 46392-2025县域无障碍环境建设评价规范
- DB32-T 4285-2022 预应力混凝土空心方桩基础技术规程
- 刺杀操课件教学课件
- 福建省厦门市双十中学2026届数学九年级第一学期期末复习检测模拟试题含解析
评论
0/150
提交评论