Как выполнить команду оболочки в Javascript

127

Я хочу написать функцию JavaScript, которая будет выполнять команды системной оболочки ( lsнапример) и возвращать значение.

Как мне этого добиться?

Сунил Кумар Саху
источник
4
где бы вы хотели выполнить эту команду, на клиенте или на сервере?
Ян Ганчич
Какую операционную систему вы используете?
Андерсон Грин
Вот руководство о том, как это сделать с помощью node.js для сценария оболочки: dreamsyssoft.com/javascript-shell-scripting/shell-tutorial.php
Rocky
7
Почему вы выбрали лучший ответ, который вам не понравился? о.0
Андре Леви
Пожалуйста, уточните, какой тип javascript. Это возможно на серверном javascript, но невозможно на клиентском javascript.
Raymond Peng

Ответы:

132

Многие другие ответы здесь, похоже, решают эту проблему с точки зрения функции JavaScript, запущенной в браузере. Я сниму и отвечу, предполагая, что, когда спрашивающий сказал «Shell Script», он имел в виду внутренний JavaScript-код Node.js. Возможно использование commander.js для использования фрейма вашего кода :)

Вы можете использовать модуль child_process из API узла. Я вставил пример кода ниже.

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

Надеюсь это поможет!

мистифицировать
источник
14
За исключением одного. Вы получите сообщение об ошибке «дочерний элемент не является функцией». Вызов exec () выполняет команду - вызывать child () не нужно. К сожалению, обратный вызов не вызывается всякий раз, когда дочерний процесс имеет что-то для вывода - он вызывается только тогда, когда дочерний процесс завершается. Иногда это нормально, а иногда нет.
Джон Дейган
2
Чтобы избежать обратных вызовов, вы можете использовать execSync .
Дэн Даскалеску
1
Кто говорил о браузере? Там написан только JavaScript, не более того.
Virus721
49

... несколько лет спустя ...

ES6 был принят в качестве стандарта, и ES7 не за горами, поэтому он заслуживает обновленного ответа. Мы будем использовать ES6 + async / await с nodejs + babel в качестве примера, предварительные условия:

Ваш пример foo.jsфайла может выглядеть так:

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

Убедитесь, что у вас есть babel:

npm i babel-cli -g

Установите последний пресет:

npm i babel-preset-latest

Запустите его через:

babel-node --presets latest foo.js
Мирек Русин
источник
3
Если вам нужно выполнить только быструю команду, все async / await будут излишними. Вы можете просто использовать execSync .
Дэн Даскалеску
Никто не просил решение для Node.js. Он говорит только о JavaScript.
Virus721
43

Я не знаю, почему предыдущие ответы давали всевозможные сложные решения. Если вы просто хотите выполнить быструю команду, например ls, вам не нужны async / await, обратные вызовы или что-то еще. Вот все, что вам нужно - 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);

Для обработки ошибок добавьте вокруг оператора блок try/ catch.

Если вы выполняете команду, выполнение которой занимает много времени, тогда да, посмотрите на асинхроннуюexec функцию.

Дэн Даскалеску
источник
19

Это полностью зависит от среды JavaScript. Пожалуйста, дополните.

Например, в Windows Scripting вы делаете такие вещи, как:

var shell = WScript.CreateObject("WScript.Shell");
shell.Run("command here");
Matt
источник
18
Возможно ли сделать то же самое в Unix-подобной операционной системе, такой как Linux?
Андерсон Грин
как запустить эту команду: route print -4 | найти \ "адаптер TAP-Windows \" ?? я попробовал, но ничего не
вернул
1
Это то, что я искал. Это раздражает всех, кто говорит о своих Node.js. Кто здесь просил Node.js? Никто этого не сделал.
Virus721
Будет ли это работать, если JavaScript находится внутри браузера?
Али Саджад,
14

В двух словах:

// 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
источник
5
Кажется, очень сложно ломать руки над тем, в каком веб-браузере это работает, но люди должны понимать, что JavaScript также является совершенно допустимым языком сценариев оболочки Windows.
Craig
6

С NodeJS все просто! И если вы хотите запускать этот скрипт при каждой загрузке вашего сервера, вы можете взглянуть на приложение forever-service !

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

exec('php main.php', function (error, stdOut, stdErr) {
    // do what you want!
});
keupsonite
источник
Чтобы избежать обратных вызовов, для быстрых команд вы можете использовать execSync .
Дэн Даскалеску
5

Примечание. Эти ответы поступают от клиента на основе браузера к веб-серверу на базе Unix.

Выполнить команду на клиенте

По сути, вы не можете. Безопасность говорит, что запускается только в браузере, и его доступ к командам и файловой системе ограничен.

Запустите ls на сервере

Вы можете использовать вызов AJAX для получения динамической страницы, передавая свои параметры через GET.

Имейте в виду, что это также создает угрозу безопасности, поскольку вам нужно будет что-то сделать, чтобы миссис Руж хакер не заставила ваше приложение сказать: run: / dev / null && rm -rf / ......

Итак, вкратце, запуск из JS - это просто плохая идея .... YMMV

Wayne
источник
По сути, вы не можете использовать кросс-браузер. Я считаю, что только IE имеет крючки в оболочке (через WSript / ActiveX).
Джастин Джонсон,
3

В IE вы можете сделать это:

var shell = new ActiveXObject("WScript.Shell");
shell.run("cmd /c dir & pause");
nonozor
источник
3

Вот простая команда, которая выполняет ifconfigкоманду оболочки Linux

var process = require('child_process');
process.exec('ifconfig',function (err,stdout,stderr) {
    if (err) {
        console.log("\n"+stderr);
    } else {
        console.log(stdout);
    }
});
Ануп Панвар
источник
Чтобы избежать обратных вызовов, вы можете использовать execSync .
Дэн Даскалеску
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);
}

Эту функцию можно легко использовать как:

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

exec('echo test', function(err, stdout){console.log(stdout+stdout+stdout)});
//output:
//testtesttest
AliFurkan
источник
1

С помощью nashorn вы можете написать такой сценарий:

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

и запустите его:

jjs -scripting each_file.js
Мацек Лозиньски
источник
0

Если вы используете npm, вы можете использовать пакет shelljs

Установить: npm install [-g] shelljs

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

Подробнее: https://www.npmjs.com/package/shelljs

Эмма
источник