简体   繁体   English

如何在Golang中杀死差异Function中的命令Exec

[英]How to kill command Exec in difference Function in Golang

i'm making screen record web based using command exec to run FFMPEG.我正在制作基于使用命令 exec 运行 FFMPEG 的屏幕记录 web。 here I created a startRecording function but I am still confused about stopping the command process in the stopRecording function, because the command is executed in the startRecording function.这里我创建了一个startRecording function 但是我仍然对在stopRecording function中停止命令进程感到困惑,因为命令是在startRecording ZC1C425268E68385D1AB50741C中执行的How to stop a process that is already running in the srartRecording function in the stopRecording function?如何在stopRecording function中停止一个已经在srartRecording function中运行的进程?

here my code这是我的代码

//Handler to create room/start record
func RoomCreate(c *fiber.Ctx) error {
    fileName := "out.mp4"
    fmt.Println(fileName)
    if len(os.Args) > 1 {
        fileName = os.Args[1]
    }

    

    errCh := make(chan error, 2)
    ctx, cancelFn := context.WithCancel(context.Background())
    // Call to function startRecording
    go func() { errCh <- startRecording(ctx, fileName) }()

    go func() {
        errCh <- nil
    }()
    err := <-errCh
    cancelFn()
    if err != nil && err != context.Canceled {
        log.Fatalf("Execution failed: %v", err)
    }
    
    return c.Redirect(fmt.Sprintf("/room/%s", guuid.New().String()))
}



//Function to run command FFMPEG
func startRecording(ctx context.Context, fileName string) error {
    ctx, cancelFn := context.WithCancel(ctx)
    defer cancelFn()
    // Build ffmpeg
    ffmpeg := exec.Command("ffmpeg",
        "-f", "gdigrab",
        "-framerate", "30",
        "-i", "desktop",
        "-f", "mp4",
        fileName,
    )
    // Stdin for sending data
    stdin, err := ffmpeg.StdinPipe()
    if err != nil {
        return err
    }
    //var buf bytes.Buffer
    defer stdin.Close()
    // Run it in the background
    errCh := make(chan error, 1)

    go func() {
        fmt.Printf("Executing: %v\n", strings.Join(ffmpeg.Args, " "))
        
        if err := ffmpeg.Run(); err != nil {
            return
        }
        //fmt.Printf("FFMPEG output:\n%v\n", string(out))
        errCh <- err
    }()
    // Just start sending a bunch of frames
    for {
        
        // Check if we're done, otherwise go again
        select {
        case <-ctx.Done():
            return ctx.Err()
        case err := <-errCh:
            return err
        default:
        }
    }
}

//Here function to stop Recording
func stopRecording(ctx context.Context) error {
//Code stop recording in here
} 

Thanks for advance感谢提前

As requested from comments.根据评论的要求。

The basic idea is to use global storage to store your active commands.基本思想是使用全局存储来存储您的活动命令。 It doesn't necessarily be global but you need to have bigger scope so that your functions can access it.它不一定是全局的,但您需要更大的 scope 以便您的函数可以访问它。

var commands = map[string]*exec.Cmd{}

func startRecording(fileName string) error {
    ffmpeg := exec.Command("ffmpeg",
        "-f", "gdigrab",
        "-framerate", "30",
        "-i", "desktop",
        "-f", "mp4",
        fileName,
    )
    commands[fileName] = ffmpeg
    ...
}

func stopRecording(fileName string) error {
    cmd, ok := commands[fileName]
    if !ok {
        return errors.New("command not found")
    }
    defer func() {
        delete(commands, fileName)
    }()
    return cmd.Process.Kill()
}

You probably want to use sync.Mutex or sync.RWMutex to avoid concurrent map writes .您可能想要使用sync.Mutexsync.RWMutex来避免并发 map 写入

So your commands cloud look like:所以你的commands云看起来像:

type Commands strunt {
    sync.RWMutex
    items map[string]*exec.Cmd
}
// use Commands.Lock() for writing, Commands.RLock() for reading

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM