Cómo ejecutar el comando de shell en Javascript

127

Quiero escribir una función de JavaScript que ejecutará los comandos de shell del sistema ( lspor ejemplo) y devolverá el valor.

¿Cómo logro esto?

Sunil Kumar Sahoo
fuente
44
¿Dónde le gustaría ejecutar este comando, en el cliente o en el servidor?
Jan Hančič
¿Qué sistema operativo estás usando?
Anderson Green
Aquí hay un tutorial sobre cómo hacerlo usando node.js para un script de shell: dreamsyssoft.com/javascript-shell-scripting/shell-tutorial.php
Rocky Pulley
77
¿Por qué elegiste la respuesta que menos te gustó como la mejor respuesta? o.0
André Levy
Sea más específico sobre qué tipo de javascript. Esto es posible en javascript del lado del servidor pero imposible en javascript del lado del cliente.
Raymond Peng el

Respuestas:

132

Muchas de las otras respuestas aquí parecen abordar este problema desde la perspectiva de una función de JavaScript que se ejecuta en el navegador. Dispararé y responderé suponiendo que cuando el autor de la pregunta dijo "Shell Script" se refería a un JavaScript de Node.js. Posiblemente usando commander.js para usar el marco de su código :)

Puede usar el módulo child_process de la API del nodo. Pegué el código de ejemplo a continuación.

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();

¡Espero que esto ayude!

Josh
fuente
14
Excepto por una cosa. Obtendrá el error "hijo no es una función". La llamada a exec () ejecuta el comando; no es necesario llamar a child (). Desafortunadamente, la devolución de llamada no se llama cada vez que el proceso secundario tiene algo que generar, se llama solo cuando el proceso secundario finaliza. A veces está bien y otras no.
John Deighan
2
Para evitar devoluciones de llamada, puede usar execSync .
Dan Dascalescu
1
¿Quién habló de un navegador? Solo dice JavaScript, nada más.
Virus721
49

... pocos años después ...

ES6 ha sido aceptado como estándar y ES7 está a la vuelta de la esquina, por lo que merece una respuesta actualizada. Usaremos ES6 + async / await con nodejs + babel como ejemplo, los requisitos previos son:

Su foo.jsarchivo de ejemplo puede verse así:

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();

Asegúrate de tener babel:

npm i babel-cli -g

Instale el último preajuste:

npm i babel-preset-latest

Ejecútelo a través de:

babel-node --presets latest foo.js
Mirek Rusin
fuente
3
Si solo necesita ejecutar un comando rápido, toda la asíncrona / espera es exagerada. Puedes usar execSync .
Dan Dascalescu
Nadie solicitó una solución Node.js. Solo dice JavaScript.
Virus721
43

No sé por qué las respuestas anteriores dieron todo tipo de soluciones complicadas. Si solo desea ejecutar un comando rápido como ls, no necesita async / waitit o callbacks ni nada. Aquí está todo lo que necesita: 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);

Para el manejo de errores, agregue un bloque try/ catchalrededor de la declaración.

Si está ejecutando un comando que tarda mucho en completarse, entonces sí, observe la función asincrónicaexec .

Dan Dascalescu
fuente
19

Esto depende completamente del entorno de JavaScript. Por favor elabora.

Por ejemplo, en Windows Scripting, haces cosas como:

var shell = WScript.CreateObject("WScript.Shell");
shell.Run("command here");
Mate
fuente
18
¿Es posible hacer lo mismo en un sistema operativo tipo Unix como Linux?
Anderson Green
¿Cómo ejecutamos este comando: route print -4 | encontrar \ "Adaptador TAP-Windows \" ?? Lo intenté pero no devuelve nada
ikel
1
Eso es lo que estaba buscando. Es molesto para todas aquellas personas que hablan sobre su Node.js. ¿Quién pidió Node.js aquí? Nadie lo hizo.
Virus721
¿Funcionaría esto si JavaScript está dentro de un navegador?
Ali Sajjad
14

En una palabra:

// 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");
Dana
fuente
55
Parece que hay muchas dudas sobre en qué navegador web se está ejecutando esto, pero la gente debería darse cuenta de que JavaScript también es un lenguaje de scripts de shell de Windows perfectamente válido.
Craig
6

¡Con NodeJS es así de simple! Y si desea ejecutar este script en cada arranque de su servidor, puede echar un vistazo a la aplicación de servicio para siempre .

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

exec('php main.php', function (error, stdOut, stdErr) {
    // do what you want!
});
keupsonita
fuente
Para evitar devoluciones de llamada, para comandos rápidos puede usar execSync .
Dan Dascalescu
5

Nota: Estas respuestas son de un cliente basado en navegador a un servidor web basado en Unix.

Ejecutar comando en el cliente

Básicamente no puedes. Seguridad dice que solo se ejecuta dentro de un navegador y su acceso a los comandos y al sistema de archivos es limitado.

Ejecute ls en el servidor

Puede usar una llamada AJAX para recuperar una página dinámica que pasa sus parámetros a través de un GET.

Tenga en cuenta que esto también abre un riesgo de seguridad, ya que tendría que hacer algo para asegurarse de que mrs rouge hacker no haga que su aplicación diga ejecutar: / dev / null && rm -rf / ......

Entonces, en pocas palabras, huir de JS es solo una mala, mala idea ... YMMV

Wayne
fuente
Básicamente, no puede hacerlo de manera cruzada. Creo que solo IE tiene ganchos en el shell (a través de WSript / ActiveX).
Justin Johnson
3

En IE, puedes hacer esto:

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

Aquí hay un comando simple que ejecuta el ifconfigcomando de shell de Linux

var process = require('child_process');
process.exec('ifconfig',function (err,stdout,stderr) {
    if (err) {
        console.log("\n"+stderr);
    } else {
        console.log(stdout);
    }
});
Anup Panwar
fuente
Para evitar devoluciones de llamada, puede usar 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);
}

Esta función se puede usar fácilmente como:

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

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

Con nashorn puedes escribir un script como este:

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

y ejecutarlo:

jjs -scripting each_file.js
Maciek Łoziński
fuente
0

Si está usando npm, puede usar el paquete shelljs

Instalar: npm install [-g] shelljs

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

Ver más: https://www.npmjs.com/package/shelljs

Emma
fuente