Go语言执行cmd命令库

这篇具有很好参考价值的文章主要介绍了Go语言执行cmd命令库。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Go语言执行cmd命令库

有时候我们需要通过代码的方式去执行 linux 命令,那么 os/exec 这个系统库刚好提供了相应的功能。

Golang语言中提供了一个 os/exec 包,它提供了一组函数和结构,用于调用外部程序,这些外部程序可以是系统

自带的,也可以是用户自定义的。os/exec 包中提供了一组函数,用于执行系统命令,我们可以使用它来执行系

统的cmd命令行。

exec包执行外部命令,它将 os.StartProcess 进行包装使得它更容易映射到 stdin 和 stdout,并且利用 pipe 连接

i/o。

参考文档:https://pkg.go.dev/os/exec

1、Command方法

func Command(name string, arg ...string) *Cmd {}

使用 exec.Command 函数来创建一个 Cmd 结构体,该函数接受两个参数,第一个参数是要执行的命令,第二个

参数是命令行参数,比如 ls -l,那么第一个参数就是 ls,第二个参数就是 -l。

2、Run方法

func (c *Cmd) Run() error {}

使用 Run 函数来执行这个命令,Run 函数会根据我们传入的参数来执行命令,并返回一个 error 类型的结果。

3、Output方法

可以使用 Output 函数来获取命令执行的结果。

4、简单例子

package main

import (
	"fmt"
	"os/exec"
)

func main() {
	// 创建一个Cmd结构体
	cmd := exec.Command("ls", "-l", "/opt/software/")
	// // 不需要cmd.Run()
	out, err := cmd.Output()
	if err != nil {
		fmt.Println("执行命令出错: ", err)
		return
	} else {
		fmt.Println("获取命令执行结果: ", string(out))
	}
}
# 程序输出
获取命令执行结果:  总用量 0
-rw-r--r--. 1 root root 0 519 09:27 aa.txt
-rw-r--r--. 1 root root 0 519 09:27 bb.txt
-rw-r--r--. 1 root root 0 519 09:27 cc.txt
package main

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

func main() {
	// 创建一个Cmd结构体
	cmd := exec.Command("ls", "-l", "/opt/software/")
	// 设置输出
	var stdout bytes.Buffer
	cmd.Stdout = &stdout
	// 执行命令
	err := cmd.Run()
	if err != nil {
		fmt.Println("执行命令出错: ", err)
		return
	} else {
		fmt.Println("获取命令执行结果: ", stdout.String())
	}
}
# 程序输出
获取命令执行结果:  总用量 0
-rw-r--r--. 1 root root 0 519 09:27 aa.txt
-rw-r--r--. 1 root root 0 519 09:27 bb.txt
-rw-r--r--. 1 root root 0 519 09:27 cc.txt

5、查找cmd命令的可执行二进制文件

LookPath 在环境变量中查找科执行二进制文件,如果file中包含一个斜杠,则直接根据绝对路径或者相对本目录

的相对路径去查找。

package main

import (
	"fmt"
	"os/exec"
)

func main() {
	f, err := exec.LookPath("ls")
	if err != nil {
		fmt.Println(err)
	}
	// /usr/bin/ls
	fmt.Println(f)
}

6、对标准输入执行cmd命令

package main

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

func main() {  
	// 进行字符串的替换
	cmd := exec.Command("tr", "a-z", "A-Z")
	cmd.Stdin = strings.NewReader("some input")  
	var out bytes.Buffer  
	cmd.Stdout = &out  
	err := cmd.Run()  
	if err != nil {  
		log.Fatal(err)  
	}  
	// in all caps: SOME INPUT
	fmt.Printf("in all caps: %s\n", out.String())
}

7、标准输出Output和CombinedOutput

// 运行命令,并返回标准输出和标准错误
func (c *Cmd) CombinedOutput() ([]byte, error)
 //运行命令并返回其标准输出
 func (c *Cmd) Output() ([]byte, error)

注意:Output() 和 CombinedOutput() 不能够同时使用,因为 command 的标准输出只能有一个,同时使用的话

便会定义了两个,便会报错。

package main

import (
	"fmt"
	"os/exec"
)

func main() {
	cmd := exec.Command("ls", "-l", "/opt/software/")
	out, err := cmd.CombinedOutput()
	if err != nil {
		fmt.Println(err) 
	}
	fmt.Println(string(out))  
}
$ go run 005.go 
total 0
-rw-r--r--. 1 root root 0 Jun 16 20:55 aa.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 bb.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 cc.txt
package main

import (
	"fmt"
	"os/exec"
)

func main() {  
    cmd := exec.Command("ls", "-l", "/opt/software/")
    out, err := cmd.Output()  
    if err != nil {  
        fmt.Println(err)  
    }  
    fmt.Println(string(out))  
}
$ go run 006.go 
total 0
-rw-r--r--. 1 root root 0 Jun 16 20:55 aa.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 bb.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 cc.txt

8、执行命令Run和Start

// 开始指定命令并且等待它执行结束,如果命令能够成功执行完毕,则返回nil,否则的话边会产生错误
func (c *Cmd) Run() error
// 使某个命令开始执行,但是并不等到他执行结束,这点和Run命令有区别,然后使用Wait方法等待命令执行完毕并且释放响应的资源        
func (c *Cmd) Start() error          

注:一个 command 只能使用 Start() 或者 Run() 中的一个启动命令,不能两个同时使用。

Start 执行不会等待命令完成,Run会阻塞等待命令完成。

下面看一下两个命令的区别:文章来源地址https://www.toymoban.com/news/detail-511223.html

package main

import (
	"log"
	"os/exec"
)

func main() {
	log.Println("start")
	cmd := exec.Command("sleep", "10")
	// 执行到此处时会阻塞等待10秒
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
	}
	log.Println("end")
}
$ go run 007-1.go 
2023/06/17 08:21:51 start
2023/06/17 08:22:01 end
package main

import (
	"log"
	"os/exec"
)

func main() {
	log.Println("start")
	cmd := exec.Command("sleep", "10")
	// 如果用start则直接向后运行
	err := cmd.Start()
	if err != nil {
		log.Fatal(err)
	}
	log.Println("end")
	// 执行Start会在此处等待10秒
	err = cmd.Wait()
	if err != nil {
		log.Fatal(err)
	}
	log.Println("wait")
}
$ go run 007-2.go 
2023/06/17 08:23:53 start
2023/06/17 08:23:53 end
2023/06/17 08:24:03 wait

9、管道Pipe

// StderrPipe返回一个pipe,这个管道连接到command的标准错误,当command命令退出时,wait将关闭这些pipe
func (c *Cmd) StderrPipe() (io.ReadCloser, error)
// StdinPipe返回一个连接到command标准输入的管道pipe
func (c *Cmd) StdinPipe() (io.WriteCloser, error)
// StdoutPipe返回一个连接到command标准输出的管道pipe
func (c *Cmd) StdoutPipe() (io.ReadCloser, error)
package main

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

func main() {
	cmd := exec.Command("cat")
	stdin, err := cmd.StdinPipe()
	if err != nil {
		fmt.Println(err)
	}
	_, err = stdin.Write([]byte("tmp.txt"))
	if err != nil {
		fmt.Println(err)
	}
	stdin.Close()
	// 终端标准输出tmp.txt
	cmd.Stdout = os.Stdout
}
$ go run 008.go
tmp.txt
package main

import (
	"io/ioutil"
	"log"
	"os/exec"
)

func main() {
	cmd := exec.Command("ls", "-l", "/opt/software/")
	// 获取输出对象,可以从该对象中读取输出结果
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	// 保证关闭输出流
	defer stdout.Close()
	// 运行命令
	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}
	// 读取输出结果
	if opBytes, err := ioutil.ReadAll(stdout); err != nil {
		log.Fatal(err)
	} else {
		log.Println(string(opBytes))
	}
	if err := cmd.Wait(); err != nil {
		log.Fatal(err)
	}
}
$ go run 009.go
total 0
-rw-r--r--. 1 root root 0 Jun 16 20:55 aa.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 bb.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 cc.txt

10、将命令的输出结果重定向到文件中

package main

import (
	"log"
	"os"
	"os/exec"
)

func main() {
	cmd := exec.Command("ls", "-l", "/opt/software/")
	stdout, err := os.OpenFile("stdout.log", os.O_CREATE|os.O_WRONLY, 0600)
	if err != nil {
		log.Fatalln(err)
	}
	defer stdout.Close()
	// 重定向标准输出到文件
	cmd.Stdout = stdout
	// 执行命令
	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}
	if err := cmd.Wait(); err != nil {
		log.Fatal(err)
	}
}
# 查看生成的文件的内容
total 0
-rw-r--r--. 1 root root 0 Jun 16 20:55 aa.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 bb.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 cc.txt

11、Wait

// Wait等待command退出,它必须和Start一起使用,如果命令能够顺利执行完并顺利退出则返回nil,否则的话便会返回error,其中Wait会是放掉所有与cmd命令相关的资源
func (c *Cmd) Wait() error
package main

import (
	"io/ioutil"
	"log"
	"os/exec"
)

func main() {
	cmd := exec.Command("ls", "-l", "/opt/software/")
	// 指向cmd命令的stdout
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	defer stdout.Close()
	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}
	if opBytes, err := ioutil.ReadAll(stdout); err != nil {
		log.Fatal(err)
	} else {
		log.Println(string(opBytes))
	}
	if err := cmd.Wait(); err != nil {
		log.Fatal(err)
	}
}
$ go run 011.go 
total 0
-rw-r--r--. 1 root root 0 Jun 16 20:55 aa.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 bb.txt
-rw-r--r--. 1 root root 0 Jun 16 20:56 cc.txt
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"os/exec"
)

func main() {
	cmd := exec.Command("echo", "-n", `{"Name": "Bob", "Age": 32}`)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}
	var person struct {
		Name string
		Age  int
	}
	if err := json.NewDecoder(stdout).Decode(&person); err != nil {
		log.Fatal(err)
	}
	if err := cmd.Wait(); err != nil {
		log.Fatal(err)
	}
	// Bob is 32 years old
	fmt.Printf("%s is %d years old\n", person.Name, person.Age)
}

12、执行过程中想要杀死cmd的执行

package main

import (
	"context"
	"fmt"
	"log"
	"os/exec"
	"time"
)

func main() {
	log.Println("start")
	CanKillRun()
	log.Println("end")
}

// 执行完发挥的数据结构
type result struct {
	err    error
	output []byte
}

// 能够杀死的进程
func CanKillRun() {
	var (
		cmd        *exec.Cmd
		ctx        context.Context
		cancelFunc context.CancelFunc
		resultChan chan *result
		res        *result
	)
	// 创建一个通道用户协程交换数据
	resultChan = make(chan *result, 1000)
	// 拿到这个上下文的取消方法
	ctx, cancelFunc = context.WithCancel(context.TODO())
	// 起一个goroutine可以理解是子进程去处理
	go func() {
		var (
			output []byte
			err    error
		)
		cmd = exec.CommandContext(ctx, "bash", "-c", "sleep 3;echo hello;")
		// 执行任务,捕捉输出
		output, err = cmd.CombinedOutput()
		// 把任务执行结果输出给main协程
		resultChan <- &result{
			err:    err,
			output: output,
		}
	}()
	// 1s后我们就把他杀死
	// 继续往下走
	time.Sleep(1 * time.Second)
	// 取消上下文
	cancelFunc()
	// 读取通道里面的数据
	res = <-resultChan
	// 打印结果
	fmt.Println("err: ", res.err, " out: ", string(res.output))
}
$ go run 013.go 
2023/06/17 08:36:52 start
err:  signal: killed  out:  
2023/06/17 08:36:55 end

13、执行脚本并获取结果

package main

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

/*
test.sh脚本内容
#!/bin/bash

for k in $( seq 1 10 )
do
   echo "Hello World $k"
   sleep 1
done
*/

var contentArray = make([]string, 0, 5)

func main() {
	command := "/bin/bash"
	params := []string{"-c", "sh test.sh"}
	execCommand(command, params)
}

func execCommand(commandName string, params []string) bool {
	contentArray = contentArray[0:0]
	cmd := exec.Command(commandName, params...)
	// 显示运行的命令
	fmt.Printf("执行命令: %s\n", strings.Join(cmd.Args, " "))
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Fprintln(os.Stderr, "error=>", err.Error())
		return false
	}
	// Start开始执行包含的命令,但并不会等待该命令完成即返回
	// wait方法会返回命令的返回状态码并在命令返回后释放相关的资源
	cmd.Start()
	reader := bufio.NewReader(stdout)
	var index int
	// 实时循环读取输出流中的一行内容
	for {
		line, err2 := reader.ReadString('\n')
		if err2 != nil || io.EOF == err2 {
			break
		}
		fmt.Println(line)
		index++
		contentArray = append(contentArray, line)
	}
	cmd.Wait()
	return true
}
$ go run 014.go 
执行命令: /bin/bash -c sh test.sh
Hello World 1

Hello World 2

Hello World 3

Hello World 4

Hello World 5

Hello World 6

Hello World 7

Hello World 8

Hello World 9

Hello World 10

到了这里,关于Go语言执行cmd命令库的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • M330左键有时候按下没反应的解决 - 换微动

    罗技M330鼠标左键有时候按下没反应,原因是微动老了要换新的了。 1、电烙铁/锡条(最主要的是这两个,其他可以不需要,操作电烙铁时候一定要小心,不要碰到被烫到) 2、小号螺丝刀,给眼镜用的那种,用来拆鼠标的螺丝(共2个螺丝) 视频教程: https://www.bilibili.com/vi

    2024年02月09日
    浏览(48)
  • Go语言执行cmd命令库

    有时候我们需要通过代码的方式去执行 linux 命令,那么 os/exec 这个系统库刚好提供了相应的功能。 Golang语言中提供了一个 os/exec 包,它提供了一组函数和结构,用于调用外部程序,这些外部程序可以是系统 自带的,也可以是用户自定义的。 os/exec 包中提供了一组函数,用于

    2024年02月11日
    浏览(9)
  • 在Android Studio导入一个项目之后,通常需要下载Gradle的相应版本,但是AS的自动下载很慢,有时候甚至会失败。会出现类似Error:connect time out等错误...

    在Android Studio导入一个项目之后,通常需要下载Gradle的相应版本,但是AS的自动下载很慢,有时候甚至会失败。会出现类似Error:connect time out等错误...

    用Android Studio导入一个项目时,用Gradle构建过程中报错误,估计是下载gradle.zip文件时访问不到,应该是被墙了,网速太慢,下载不了外网资源。错误有如下情况:1、加载过慢2、下载超时3、下载失败 解决方法如下: 1、下载对应的gradle版本 在Project的视图下,找到gradle,里面的

    2024年02月03日
    浏览(51)
  • cmd 执行 nvm 的时候报错没有此命令。

    安装 nvm-windows 菜鸟教程 如果你已经安装了 nodejs 就要提前把它卸载掉 安装 node, 根据所需版本进行安装 nodejs 例如 nvm install xxx node官网 nvm use node , 如果你的 node 安装成功了,记得还要 nvm use xxx(版本号),如果不use一下,相当于当前没有使用node环境,node是不可用的命令, 如果

    2024年02月11日
    浏览(9)
  • go语言中的init() 函数是什么时候执行的?

    在main函数之前执行 init()函数是go初始化的一部分,由runtime初始化每个导入的包,初始化不是按照从上到下的导入顺序,而是按照解析的依赖关系, 没有依赖的包最先初始化 。   每个包首 先初始化包作用域的常量和变量 (常量优先于变量),然 后执行包的 init() 函数 。同

    2024年02月15日
    浏览(7)
  • 17.1 隐藏执行CMD命令

    17.1 隐藏执行CMD命令

    本章内容涉及使用 Socket API 和 CMD 命令行工具实现本地 CMD 命令执行、无管道正向 CMD 和无管道反向 CMD 三种功能。执行本地 CMD 实现使用 CreateProcess 函数创建一个新的 CMD 进程,并将标准输入、输出和错误输出重定向到当前进程的标准输入、输出和错误输出。无管道正向 CMD 和

    2024年02月08日
    浏览(13)
  • python代码调出cmd命令行窗口并在cmd窗口中执行指定的命令

    有时候,我们需要在python代码中打开 cmd命令行窗口,并在新打开的命令行cmd窗口中执行特定的命令, 其实,这个操作很容易,不过在网上找了一圈,都是没有说明白, 这里总结发布一下, 导入 os 模块 import os os.system( \\\' start cmd.exe /K C:\\\\Users\\\\admin\\\\AppData\\\\Roaming\\\\360se6\\\\Applicati

    2024年02月11日
    浏览(15)
  • win10 bat执行cmd命令

    打开一个cmd界面,执行命令。需要打开多个cmd界面时,bat文件中添加多行就行。 以“”隔开多个命令, 不管前面的命令是否成功,后面的都会执行 : 以“”隔开多个命令, 前面命令执行成功时,后面才会执行 : 以“||”隔开多个命令, 前面命令执行失败时,后面才会执行

    2024年02月02日
    浏览(8)
  • 一文看懂python如何执行cmd命令

    一文看懂python如何执行cmd命令

      “  在进行Python编程时,经常需要使用到操作系统的命令行,这就要求我们学会如何使用Python执行cmd命令。 ”   Python是一种强大而灵活的编程语言,它可以很方便地执行系统命令,与操作系统进行交互。本文将介绍Python执行cmd命令的几种常用方法,以及它们的优缺点和使

    2024年02月16日
    浏览(11)
  • python执行cmd命令——控制电脑连接wifi——程序打包

    控制电脑连接wifi

    2024年02月05日
    浏览(11)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包