首页 > 系统相关 >关于如何在Windows下通过Golang调用cmd指令

关于如何在Windows下通过Golang调用cmd指令

时间:2022-11-08 18:44:06浏览次数:71  
标签:UDP err exec Windows cmd Golang Command c1

太nm操蛋了,我tm弄了两小时。

起因

目前我的项目中,当并发量提高的时候会出现UDP的buffer queue full的情况,我怀疑是因为UDP端口释放太慢导致堆积。

于是就打算用golang写一个命令行程序,每个0.5s执行以下cmd语句:

netstat -an | grep "UDP"

过程

我记得golang是有一个exec库的,专门用来跑cmd,但是忘记在哪里看到了,就去网上搜。

首先是网上的教程大多是linux环境下的,所以他们的博客对与windows下的我并不通用

这一点我试了很久...

One:

使用网上类似这样的代码:

func main() {
	c1 := exec.Command("netstat", "-an")
	c2 := exec.Command("grep", "UDP")
	c2.Stdin, _ = c1.StdoutPipe()
	c2.Stdout = os.Stdout
	_ = c2.Start()
	err := c1.Run()
	if err != nil {
		log.Panicln(err.Error())
	}
	_ = c2.Wait()
}

你就会收获如下错误

image-20221108171457567

就很懵。后来想想是因为grep是linux下的,之后就找到了windows下的代替品find

Two:

之后代码就变成下面这样:

func main() {
	c1 := exec.Command("find", "UDP")
	output, err := c1.CombinedOutput()
	if err != nil {
        fmt.Println(fmt.Sprint(err) + ": " + string(output))
		return
	}
	fmt.Println(string(output))
}

然而你运行之后会得到以下错误:

image-20221108171723991

???这是个什么错误,你倒是告诉我错误是啥啊

后来去stack overflow上找到了方法

https://stackoverflow.com/questions/18159704/how-to-debug-exit-status-1-error-when-running-exec-command-in-golang

简而言之就是,这个err会返回在cmd.Stderr上面,所以需要打印cmd.Stderr。或者调用CombinedOutput()

Three:

但是你调用之后,会得到以下结果:

image-20221108172045101

???为什么会有乱码

查资料发现是因为cmd的输入输出都是遵循GBK编码的,但是中文是UTF-8编码的,所以中文就会显示乱码。

艹cmd是什么落后的东西啊。

之后去网上嫖了一个GBK转UTF-8的:

func ConvertByte2String(byte []byte, charset Charset) string {
	var str string
	switch charset {
	case GB18030:
		var decodeBytes, _ = simplifiedchinese.GB18030.NewDecoder().Bytes(byte)
		str = string(decodeBytes)
	case UTF8:
		fallthrough
	default:
		str = string(byte)
	}
	return str
}

最后总算能显示中文了,但是显示的结果如下:

image-20221108181539612

Four:

我看cmd都是这么用的怎么到这就拉垮了?

image-20221108181703420

之后通过打印语句,看了一下以上的命令到底是什么:

image-20221108181845077

猜测可能是因为没有引号导致的,于是就加上引号,代码现在长这样:

func main() {
	c1 := exec.Command("netstat", "-an")
	c2 := exec.Command("find", "\"UDP\"", "/c")
	c2.Stdin, _ = c1.StdoutPipe()
	c2.Stdout = os.Stdout
	_ = c2.Start()
	err := c1.Run()
	if err != nil {
		log.Panicln(err.Error())
	}
	_ = c2.Wait()
}

发现貌似卡住了,根本没输出。

Five:

debug模式进入之后发现是卡在了c2.Wait()这里,这个我也不知道为什么。于是就去网上换了一种方式,来写。

突然看到一篇博客说可以直接通过调用cmd.exe之后设置参数就可以直接一句话完成我最开始想要的cmd语句。

于是现在长这样:

func main() {
	c1 := exec.Command("cmd.exe", "netstat -an | find /c \"UDP\"")
	output, err := c1.CombinedOutput()
	fmt.Println(c1.String())
	if err != nil {
		fmt.Println(fmt.Sprint(err) + ": " + ConvertByte2String(output, "GB18030"))
		return
	}
	fmt.Println(string(output))
}

结果报了这样的错误:

image-20221108182412384

?我寻思这不就是字符串参数。这个奇奇怪怪的是什么??

之后又尝试了这种写法:

c1 := exec.Command("cmd.exe", "netstat -an | find /c UDP")

image-20221108182516625

结果还是会报错...

有可能是因为cmd的转义字符跟golang的有所不同导致的,于是我采用了raw string的形式

c1 := exec.Command("cmd.exe", `netstat -an | find /c "UDP"`)

结果还是会有这样的错误...image-20221108182721761

c1 := exec.Command("cmd.exe", `netstat -an | find /c UDP`)

image-20221108182801939

Six:

就在我感到绝望的时候,我看到网上说powershell完美兼容cmd同时还会有更智能地识别,于是我就看怎么用golang调用powershell,发现只需要把之前的cmd改成powershell就可以:

c1 := exec.Command("powershell.exe", `netstat -an | find /c UDP`)

image-20221108183000344

结果还是不对,之后我去网上搜:搜到了结果

https://blog.csdn.net/beebeeyoung/article/details/116677249

c1 := exec.Command("powershell.exe", "netstat -an | find /c `\"UDP`\"")

image-20221108183142533

终于!!!!总算成功!!!!

完结撒花!!!


尾声

最后发现Prometheus地node-exporter里面自带监听端口的metric,所以只需要在grafana里面填上PromQL就可以(

标签:UDP,err,exec,Windows,cmd,Golang,Command,c1
From: https://www.cnblogs.com/Vikyanite/p/16870787.html

相关文章

  • go语言 cmd执行命令,遇到空格或者双引号无法执行成功的解决方案
    大部分go执行cmd命令都是,我也是这样写的packagemainimport("fmt""os/exec")funcmain(){cmdExec := `cmd /c "D:\test test\AnyDesk.exe"`......
  • QProcess 调用.py脚本(windows + python 环境)
    1QProcessp;2QStringListargs1;3args1.append("demo.py");//设置py脚本4p.setWorkingDirectory("d:/demo/");//设置py脚本所在目录5p......
  • windows系统无法创建任务解决方案
        甲方安排一个任务,需要定时对局域网目录共享文件进行扫描,因为扫描共享文件这块已经通过SMB协议完成,我只需要把这个程序定时执行就可以完工。一开始有两个方案,......
  • Windows - win10 开放外部访问端口
    win10开放外部访问端口直接在搜索中输入“防火墙”,然后打开“防火墙高级设置”新建入站规则 选择端口,然后下一步选择连接协议,然后输入特定的端口号,然后下一步选......
  • Golang 实现时间戳和时间的转化
    何为时间戳:时间戳是使用数字签名技术产生的数据,签名的对象包括了原始文件信息、签名参数、签名时间等信息。时间戳系统用来产生和管理时间戳,对签名对象进行数字签名产生时......
  • 在Windows8_10中使用匿名共享
    1、打开本地组策略编辑器(快捷键Win+R,打开运行,输入gpedit.msc,确定);2、打开:“本地计算机策略->计算机配置->Windows设置->安全设置->本地策略->用户权限分配”;找到:“拒绝......
  • Windows平台安装OpenSSL
    Windows平台安装openssl有两种方法,第一种是直接下载安装包进行安装、第二种是下载源站进行编译安装1.直接下载安装包进行安装(最简单)1.1下载安装包Window的openssl的安装......
  • Windows下将压缩包隐写到图片中以及相对应的提取
    Windows下将压缩包隐写到图片中以及相对应的提取其实原理非常的简单,就是进行一个压缩,只不过让它看起来像图片一样;下面是效果:实现的原理是非常简单的,使用了Windows下的命......
  • Python 获取windows硬件信息 CPU/计算机名/IP
    获取windows硬件信息#-*-coding:utf-8-*-#@Time:2022/11/811:22#@Author:lzc#@Email:[email protected]#@blog:https://www.cnblogs.com/zich......
  • windows下anaconda安装
    本来安装了miniconda,但是发现打开PowerShell后指令前没有(base),就卸载了,打算安装anaconda。关于anaconda与python版本对应问题安装anaconda后,其会在他的环境之下安装对应......