Saltar al contenido

Terminar un proceso iniciado con os/exec en Golang

Nuestros desarrolladores estrellas agotaron sus reservas de café, buscando día y noche por la resolución, hasta que Nora halló la respuesta en Gitea y en este momento la comparte contigo.

Solución:

Terminar una ejecución exec.Process:

// Start a process:
cmd := exec.Command("sleep", "5")
if err := cmd.Start(); err != nil 
    log.Fatal(err)


// Kill it:
if err := cmd.Process.Kill(); err != nil 
    log.Fatal("failed to kill process: ", err)

Terminar una ejecución exec.Process después de un tiempo de espera:

// Start a process:
cmd := exec.Command("sleep", "5")
if err := cmd.Start(); err != nil 
    log.Fatal(err)


// Wait for the process to finish or kill it after a timeout (whichever happens first):
done := make(chan error, 1)
go func() 
    done <- cmd.Wait()
()
select 
case <-time.After(3 * time.Second):
    if err := cmd.Process.Kill(); err != nil 
        log.Fatal("failed to kill process: ", err)
    
    log.Println("process killed as timeout reached")
case err := <-done:
    if err != nil 
        log.Fatalf("process finished with error = %v", err)
    
    log.Print("process finished successfully")

O el proceso finaliza y su error (si lo hay) se recibe a través de done o han pasado 3 segundos y el programa se cierra antes de que finalice.

Las otras respuestas son correctas sobre llamar Kill()pero las partes relacionadas con la finalización del proceso después de un tiempo de espera están un poco desactualizadas ahora.

Esto se puede hacer ahora con el context paquete y exec.CommandContext (ejemplo adaptado del ejemplo en los documentos):

func main() 
    ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
    defer cancel()

    if err := exec.CommandContext(ctx, "sleep", "5").Run(); err != nil 
        // This will fail after 100 milliseconds. The 5 second sleep
        // will be interrupted.
    

De los documentos:

El contexto proporcionado se usa para eliminar el proceso (llamando a os.Process.Kill) si el contexto se completa antes de que el comando se complete por sí solo.

Después de la Run() completa, puede inspeccionar ctx.Err(). Si se alcanzó el tiempo de espera, el tipo de error devuelto será DeadLineExceeded. Si es nilcomprobar el err devuelto por Run() para ver si el comando se completó sin errores.

Una versión más simple sin seleccionar y canales.

func main() 
    cmd := exec.Command("cat", "/dev/urandom")
    cmd.Start()
    timer := time.AfterFunc(1*time.Second, func() 
        err := cmd.Process.Kill()
        if err != nil 
            panic(err) // panic as can't kill a process.
        
    )
    err := cmd.Wait()
    timer.Stop()

    // read error from here, you will notice the kill from the 
    fmt.Println(err)

Bueno, después de consultar a un programador de go experimentado, aparentemente esta no es una forma lo suficientemente GOly de resolver el problema. Por lo tanto, consulte la respuesta aceptada.


Aquí hay una versión aún más corta y muy sencilla. PERO, posiblemente tenga toneladas de rutinas pendientes si el tiempo de espera es largo.

func main() 
    cmd := exec.Command("cat", "/dev/urandom")
    cmd.Start()
    go func()
        time.Sleep(timeout)
        cmd.Process.Kill()
    ()
    return cmd.Wait()

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *