Ce face child_process.exec
exec pornește un shell (/bin/sh pe Linux și macOS, cmd.exe pe Windows) și îi dă comanda ca text. Poți folosi tot ce merge în terminal: pipe-uri (|), redirecționări, &&. Când comanda se termină, primești ieșirea ei completă (stdout și stderr) în funcția de callback.
execSync face același lucru sincron: blochează programul până termină comanda și întoarce ieșirea. Dacă comanda iese cu cod diferit de zero, aruncă o eroare cu proprietățile status, stdout și stderr. Varianta cu promisiuni se obține cu util.promisify(exec), care întoarce { stdout, stderr }.
Ieșirea este ținută în memorie (implicit maxim 1 MB, opțiunea maxBuffer). Pentru comenzi care afișează mult sau rulează mult timp folosește spawn. Și cel mai important: nu pune niciodată în comandă text primit de la utilizator, pentru că shell-ul l-ar interpreta (injectare de comenzi). Pentru argumente variabile folosește execFile.
Parametri
| Parametru | Descriere |
|---|---|
comanda |
Textul comenzii, exact ca în terminal. |
opțiuni.cwd |
Directorul în care rulează comanda. |
opțiuni.env |
Variabilele de mediu (implicit cele ale procesului). |
opțiuni.encoding |
"utf8" implicit la exec; la execSync fără ea primești un Buffer. |
opțiuni.timeout |
Oprește comanda după atâtea milisecunde. |
Ce returnează
exec: obiectul ChildProcess. execSync: ieșirea comenzii.
Exemple
Exemplul 1: Comandă cu pipe, varianta cu promisiuni
import { exec } from "node:child_process";
import { promisify } from "node:util";
import { writeFileSync } from "node:fs";
const execAsync = promisify(exec);
writeFileSync("orase.txt", "Iași\nCluj\nBrașov\nArad\n");
const { stdout } = await execAsync("sort orase.txt | head -n 2");
console.log(stdout.trim().split("\n"));
Rezultat
[ 'Arad', 'Brașov' ]
Exemplul 2: execSync și codul de ieșire
O comandă care eșuează aruncă o eroare. stdio cu "pipe" împiedică mesajul de eroare al comenzii să apară direct în terminal.
import { execSync } from "node:child_process";
const versiune = execSync("node -p process.versions.node", { encoding: "utf8" });
console.log("Node major:", versiune.split(".")[0]);
try {
execSync("ls fisier-care-nu-exista", { stdio: "pipe" });
} catch (eroare) {
console.log("Comanda a eșuat cu codul", eroare.status);
}
Rezultat
Node major: 26
Comanda a eșuat cu codul 1
Exemplul 3: Callback cu eroare, stdout și stderr
import { exec } from "node:child_process";
exec("echo Salut din shell && echo atenție 1>&2", (eroare, stdout, stderr) => {
if (eroare) throw eroare;
console.log("stdout:", stdout.trim());
console.log("stderr:", stderr.trim());
});
Rezultat
stdout: Salut din shell
stderr: atenție
Greșeli frecvente
- Construiești comanda din date primite:
exec(`cat ${numeFisier}`). Dacă cineva trimitea.txt; rm -rf ~, shell-ul rulează și a doua comandă. FoloseșteexecFile("cat", [numeFisier]). - Rulezi cu
execo comandă care afișează mult (unfindmare): pestemaxBufferprocesul este oprit cuERR_CHILD_PROCESS_STDIO_MAXBUFFER. Foloseștespawnși citește ieșirea ca stream. - Folosești
execSyncîntr-un server web: blochează toate cererile cât rulează comanda. Pe server folosește variantele asincrone.
Comenzi înrudite
child_process.execFile: Rulează direct un program cu argumente separate, fără shell, și primește ieșirea la final. Varianta sigură a lui exec.child_process.spawn: Pornește un program ca proces copil și citește ieșirea lui pe măsură ce apare (stream), fără shell.util.promisify: Transformă o funcție cu callback în stil Node.js (eroare, rezultat) într-o funcție care întoarce o promisiune.process.exit / process.exitCode: Stabilește codul de ieșire al scriptului (0 = succes) sau oprește procesul imediat cu process.exit.