--- name: process_spawn kind: function lang: go domain: infra version: "1.0.0" purity: impure signature: "func ProcessSpawn(command string, dir string, env []string, shell string) (*ProcessHandle, error)" description: "Lanza un subproceso usando el shell indicado. Si shell esta vacio usa 'sh'. Comandos con newlines se tratan como scripts multilinea (se escriben a un archivo temporal). Configura un process group propio (Setpgid) para poder matar todos los hijos con ProcessKill. Captura stdout y stderr via pipes." tags: [process, subprocess, spawn, exec, shell, infra] uses_functions: [] uses_types: [process_handle_go_infra] returns: [process_handle_go_infra] returns_optional: false error_type: "error_go_core" imports: [fmt, os, os/exec, strings, syscall, time] params: - name: command desc: "comando shell a ejecutar; si contiene newlines se trata como script multilinea" - name: dir desc: "directorio de trabajo del proceso hijo; vacio hereda el del proceso padre" - name: env desc: "variables de entorno en formato KEY=VALUE; nil hereda el entorno del proceso padre" - name: shell desc: "interprete shell a usar (sh, bash, zsh); vacio usa 'sh'" output: "handle del proceso lanzado con Cmd, Pid, StartTime, Dir y los pipes de I/O" tested: true tests: - "spawn and wait echo" - "spawn with timeout kills" - "spawn with env" - "spawn script" - "spawn with working dir" - "kill process" test_file_path: "functions/infra/process_spawn_test.go" file_path: "functions/infra/process_spawn.go" --- ## Ejemplo ```go h, err := ProcessSpawn("echo hello", "", nil, "") if err != nil { log.Fatal(err) } res, err := ProcessWait(h, 10) fmt.Println(res.Stdout) // "hello\n" ``` ## Notas Funcion impura: hace I/O (crea archivo temporal para scripts, lanza proceso). El process group (Setpgid=true) permite a ProcessKill enviar senales al grupo completo con -Pid, afectando a todos los hijos del proceso lanzado. Para scripts multilinea el archivo temporal queda en el directorio temporal del OS y no se limpia automaticamente.