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 nil
comprobar 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()