Come eseguire il comando shell in Javascript


127

Voglio scrivere una funzione JavaScript che eseguirà i comandi della shell di sistema ( lsad esempio) e restituirà il valore.

Come posso raggiungere questo obiettivo?


4
dove vorresti eseguire questo comando, sul client o sul server?
Jan Hančič,

Quale sistema operativo stai usando?
Anderson Green,

Ecco un tutorial su come farlo usando node.js per uno script di shell: dreamsyssoft.com/javascript-shell-scripting/shell-tutorial.php
Rocky Pulley

7
Perché hai scelto la risposta più antipatica come la migliore risposta? o.0
André Levy,

Si prega di essere più specifici su quale tipo di javascript. Ciò è possibile su JavaScript lato server ma impossibile su JavaScript lato client.
Raymond Peng,

Risposte:


132

Molte delle altre risposte qui sembrano affrontare questo problema dal punto di vista di una funzione JavaScript in esecuzione nel browser. Sparo e rispondo supponendo che quando l'interrogante ha detto "Shell Script" intendesse un backend Node.js JavaScript. Forse usando commander.js per usare il frame del tuo codice :)

È possibile utilizzare il modulo child_process dall'API del nodo. Ho incollato il seguente codice di esempio.

var exec = require('child_process').exec, child;

child = exec('cat *.js bad_file | wc -l',
    function (error, stdout, stderr) {
        console.log('stdout: ' + stdout);
        console.log('stderr: ' + stderr);
        if (error !== null) {
             console.log('exec error: ' + error);
        }
    });
 child();

Spero che questo ti aiuti!


14
Tranne una cosa. Verrà visualizzato l'errore "figlio non è una funzione". La chiamata a exec () esegue il comando - non è necessario chiamare child (). Sfortunatamente, il callback non viene chiamato ogni volta che il processo figlio ha qualcosa da emettere - viene chiamato solo quando il processo figlio termina. A volte va bene, a volte no.
John Deighan,

2
Per evitare callback, è possibile utilizzare execSync .
Dan Dascalescu,

1
Chi ha parlato di un browser? Dice solo JavaScript, niente di più.
Virus721

49

... qualche anno dopo ...

ES6 è stato accettato come standard ed ES7 è dietro l'angolo, quindi merita una risposta aggiornata. Useremo ES6 + async / waitit con nodejs + babel come esempio, i prerequisiti sono:

Il tuo foo.jsfile di esempio potrebbe apparire come:

import { exec } from 'child_process';

/**
 * Execute simple shell command (async wrapper).
 * @param {String} cmd
 * @return {Object} { stdout: String, stderr: String }
 */
async function sh(cmd) {
  return new Promise(function (resolve, reject) {
    exec(cmd, (err, stdout, stderr) => {
      if (err) {
        reject(err);
      } else {
        resolve({ stdout, stderr });
      }
    });
  });
}

async function main() {
  let { stdout } = await sh('ls');
  for (let line of stdout.split('\n')) {
    console.log(`ls: ${line}`);
  }
}

main();

Assicurati di avere una babele:

npm i babel-cli -g

Installa le preimpostazioni più recenti:

npm i babel-preset-latest

Eseguilo tramite:

babel-node --presets latest foo.js

3
Se hai solo bisogno di eseguire un comando rapido, tutto l'asincrono / attende è eccessivo. Puoi semplicemente usare execSync .
Dan Dascalescu,

Nessuno ha chiesto una soluzione Node.js. Dice solo JavaScript.
Virus721

43

Non so perché le risposte precedenti offrissero ogni sorta di soluzioni complicate. Se vuoi solo eseguire un comando rapido come ls, non hai bisogno di asincronizzazione / wait o callback o altro. Ecco tutto ciò di cui hai bisogno - execSync :

const execSync = require('child_process').execSync;
// import { execSync } from 'child_process';  // replace ^ if using ES modules
const output = execSync('ls', { encoding: 'utf-8' });  // the default is 'buffer'
console.log('Output was:\n', output);

Per la gestione degli errori, aggiungere un blocco try/ catchattorno all'istruzione.

Se stai eseguendo un comando che richiede molto tempo per il completamento, quindi sì, guarda la funzione asincronaexec .


19

Questo dipende interamente dall'ambiente JavaScript. Per favore, elabora.

Ad esempio, in Windows Scripting, fai cose come:

var shell = WScript.CreateObject("WScript.Shell");
shell.Run("command here");

18
È possibile fare la stessa cosa in un sistema operativo simile a Unix come Linux?
Anderson Green,

come eseguiamo questo comando: route print -4 | trova \ "TAP-Windows Adapter \" ?? ho provato ma non restituisce nulla
Ikel

1
Questo è quello che stavo cercando. È fastidioso tutte quelle persone che parlano del loro Node.js. Chi ha chiesto Node.js qui? Nessuno l'ha fatto.
Virus721

Funzionerebbe se JavaScript si trova all'interno di un browser?
Ali Sajjad

14

In breve:

// Instantiate the Shell object and invoke its execute method.
var oShell = new ActiveXObject("Shell.Application");

var commandtoRun = "C:\\Winnt\\Notepad.exe";
if (inputparms != "") {
  var commandParms = document.Form1.filename.value;
}

// Invoke the execute method.  
oShell.ShellExecute(commandtoRun, commandParms, "", "open", "1");


5
Sembra che ci sia molta scrittura a mano su quale browser web è in esecuzione, ma la gente dovrebbe rendersi conto che JavaScript è anche un linguaggio di scripting della shell di Windows perfettamente valido.
Craig,

6

Con NodeJS è così semplice! E se si desidera eseguire questo script ad ogni avvio del server, è possibile avere uno sguardo sul forever-service applicazione!

var exec = require('child_process').exec;

exec('php main.php', function (error, stdOut, stdErr) {
    // do what you want!
});

Per evitare richiamate, per comandi rapidi è possibile utilizzare execSync .
Dan Dascalescu,

5

Nota: queste risposte provengono da un client basato su browser a un server Web basato su Unix.

Esegui il comando sul client

Non puoi essenzialmente. La sicurezza dice che funziona solo all'interno di un browser e il suo accesso a comandi e filesystem è limitato.

Esegui ls sul server

È possibile utilizzare una chiamata AJAX per recuperare una pagina dinamica che passa i parametri tramite GET.

Essere consapevoli del fatto che ciò comporta anche un rischio per la sicurezza in quanto si dovrebbe fare qualcosa per assicurarsi che la signora hacker rouge non riesca a far eseguire la propria applicazione: / dev / null && rm -rf / ......

Quindi, in poche parole, correre da JS è solo una cattiva, cattiva idea ... YMMV


Fondamentalmente non è possibile in un modo cross-browser. Credo che solo IE abbia hook nella shell (tramite WSript / ActiveX).
Justin Johnson,


3

In IE, puoi farlo:

var shell = new ActiveXObject("WScript.Shell");
shell.run("cmd /c dir & pause");

3

Ecco un semplice comando che esegue il ifconfigcomando shell di Linux

var process = require('child_process');
process.exec('ifconfig',function (err,stdout,stderr) {
    if (err) {
        console.log("\n"+stderr);
    } else {
        console.log(stdout);
    }
});

Per evitare callback, è possibile utilizzare execSync .
Dan Dascalescu,

3
function exec(cmd, handler = function(error, stdout, stderr){console.log(stdout);if(error !== null){console.log(stderr)}})
{
    const childfork = require('child_process');
    return childfork.exec(cmd, handler);
}

Questa funzione può essere facilmente utilizzata come:

exec('echo test');
//output:
//test

exec('echo test', function(err, stdout){console.log(stdout+stdout+stdout)});
//output:
//testtesttest

1

Con nashorn puoi scrivere una sceneggiatura come questa:

$EXEC('find -type f');
var files = $OUT.split('\n');
files.forEach(...
...

ed eseguilo:

jjs -scripting each_file.js

0

Se stai usando npm puoi usare il pacchetto shelljs

Installare: npm install [-g] shelljs

var shell = require('shelljs');
shell.ls('*.js').forEach(function (file) {
// do something
});

Scopri di più: https://www.npmjs.com/package/shelljs

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.