Estoy desarrollando un script de compilación de nodo pequeño que quiero iniciar WSL, cd en el directorio de mi proyecto e invocar un comando de compilación. Algo como esto:
import { exec } from "child_process"; async function execCommand(cmd) { console.log("Executing: " + cmd); return new Promise((resolve, reject) => { exec(cmd, (error, stdout, stderr) => { if (error) { reject(); } else { resolve(); } }); }); } await execCommand(`wsl`); await execCommand(`cd /mnt/c/Users/Admin/Documents/Projects/myproject/backend`); await execCommand(`cargo build --release`); Mi problema es que simplemente... no funciona. Es decir, el primer execCommand llama a wsl y luego parece que la ventana de la terminal nunca completa el comando (nunca termina).
En su lugar, solicita al usuario que escriba algo en el símbolo del sistema.
¿Cuál es la forma correcta de iniciar WSL desde un script de nodo y luego encadenar un montón de comandos, cada uno esperando que termine el anterior?
Finalmente lo hice funcionar.
Versión asíncrona:
let child = spawn("wsl", [ "cd", "/mnt/c/Users/Admin/Documents/Projects/myserver/backend", "&&", "cargo", "build", "--release" ], { cwd: "C:\\Users\\Admin\\Documents\\Projects\\myserver\\backend", shell: true }); child.stdout.pipe(process.stdout); child.stderr.pipe(process.stderr); child.stdin.end();Versión síncrona:
let child = spawnSync("wsl", [ "cd", "/mnt/c/Users/Admin/Documents/Projects/myserver/backend", "&&", "cargo", "build", "--release" ], { cwd: "C:\\Users\\Admin\\Documents\\Projects\\myserver\\backend", shell: true }); console.log(child.stdout.toString()); console.log(child.stderr.toString());En realidad, mi otra respuesta no es tan buena, porque inicia un shell separado y ejecuta los comandos a través del shell cmd en su lugar, por lo que Windows construirá el binario en lugar de WSL, que no es lo que queremos. Una mejor respuesta es:
let child = spawnSync("wsl", [ "bash", "-l", "-c", "cargo build --release" ], { cwd: "C:\\Users\\Admin\\Documents\\Projects\\myserver\\backend" }); console.log(child.stdout.toString()); console.log(child.stderr.toString()); Debe incluir bash -l porque cuando ejecuta un comando a través wsl , no ejecuta ~/.profile y ~/.bashrc (etc). Cargo necesita eso para poder insertar ~/.cargo/bin en $PATH .
Entonces, con bash -l lo fuerza a ejecutar los scripts de inicio del perfil. Cuando inicia WSL sin ningún otro comando, iniciará sesión de forma interactiva, lo que significa que esos scripts se ejecutan.