Jak wykonać polecenie powłoki w Javascript

127

Chcę napisać funkcję JavaScript, która wykona polecenia powłoki systemu ( lsna przykład) i zwróci wartość.

Jak to osiągnąć?

Sunil Kumar Sahoo
źródło
4
gdzie chciałbyś wykonać to polecenie, na kliencie czy na serwerze?
Jan Hančič
Z jakiego systemu operacyjnego korzystasz?
Anderson Green,
Oto samouczek, jak to zrobić za pomocą node.js dla skryptu powłoki: dreamsyssoft.com/javascript-shell-scripting/shell-tutorial.php
Rocky Pulley
7
Dlaczego wybrałeś najbardziej nielubianą odpowiedź jako najlepszą? o.0
André Levy
Podaj bardziej szczegółowe informacje na temat typu kodu JavaScript. Jest to możliwe w javascript po stronie serwera, ale niemożliwe w javascript po stronie klienta.
Raymond Peng

Odpowiedzi:

132

Wydaje się, że wiele innych odpowiedzi tutaj rozwiązuje ten problem z perspektywy funkcji JavaScript działającej w przeglądarce. Strzelę i odpowiem zakładając, że kiedy pytający powiedział „Skrypt powłoki”, miał na myśli JavaScript zaplecza Node.js. Możliwe, że używasz commander.js do ramki swojego kodu :)

Możesz użyć modułu child_process z interfejsu API węzła. Wkleiłem poniższy przykładowy kod.

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

Mam nadzieję że to pomoże!

Josh
źródło
14
Poza jedną rzeczą. Pojawi się błąd „dziecko nie jest funkcją”. Wywołanie exec () wykonuje polecenie - nie ma potrzeby wywoływania funkcji child (). Niestety, wywołanie zwrotne nie jest wywoływane za każdym razem, gdy proces potomny ma coś do wyprowadzenia - jest wywoływane tylko wtedy, gdy proces potomny kończy pracę. Czasami jest to w porządku, a czasami nie.
John Deighan
2
Aby uniknąć wywołań zwrotnych, możesz użyć execSync .
Dan Dascalescu
1
Kto mówił o przeglądarce? Mówi tylko o JavaScript, nic więcej.
Virus721,
49

... kilka lat później ...

ES6 został zaakceptowany jako standard, a ES7 jest tuż za rogiem, więc zasługuje na zaktualizowaną odpowiedź. Jako przykład użyjemy ES6 + async / await z nodejs + babel, wymagania wstępne to:

Twój przykładowy foo.jsplik może wyglądać następująco:

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

Upewnij się, że masz babel:

npm i babel-cli -g

Zainstaluj najnowsze ustawienie wstępne:

npm i babel-preset-latest

Uruchom go przez:

babel-node --presets latest foo.js
Mirek Rusin
źródło
3
Jeśli potrzebujesz tylko wykonać szybkie polecenie, cała async / await to przesada. Możesz po prostu użyć execSync .
Dan Dascalescu
Nikt nie prosił o rozwiązanie Node.js. Mówi tylko o JavaScript.
Virus721,
43

Nie wiem, dlaczego poprzednie odpowiedzi zawierały różnego rodzaju skomplikowane rozwiązania. Jeśli chcesz po prostu wykonać szybkie polecenie, takie jak ls, nie potrzebujesz async / await, callbacków ani nic. Oto wszystko, czego potrzebujesz - 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);

W celu obsługi błędów dodaj try/ catchblok wokół instrukcji.

Jeśli uruchamiasz polecenie, którego wykonanie zajmuje dużo czasu, to tak, spójrz na funkcję asynchronicznąexec .

Dan Dascalescu
źródło
19

Zależy to całkowicie od środowiska JavaScript. Proszę rozwinąć.

Na przykład podczas wykonywania skryptów systemu Windows wykonujesz następujące czynności:

var shell = WScript.CreateObject("WScript.Shell");
shell.Run("command here");
Matt
źródło
18
Czy można zrobić to samo w systemie operacyjnym podobnym do Uniksa, takim jak Linux?
Anderson Green,
jak uruchomimy to polecenie: route print -4 | znajdź \ "Adapter TAP-Windows \" ?? próbowałem, ale nic nie zwraca
ikel
1
Właśnie tego szukałem. To irytujące wszystkich tych ludzi, którzy mówią o swoich Node.js. Kto poprosił o Node.js tutaj? Nikt tego nie zrobił.
Virus721,
Czy to zadziała, jeśli JavaScript znajduje się w przeglądarce?
Ali Sajjad
14

W skrócie:

// 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
źródło
5
Wydaje się, że dużo się załatwia, w której przeglądarce internetowej to działa, ale ludzie powinni zdawać sobie sprawę, że JavaScript jest również doskonale poprawnym językiem skryptowym powłoki systemu Windows.
Craig,
6

Z NodeJS jest takie proste! A jeśli chcesz uruchamiać ten skrypt przy każdym uruchomieniu serwera, możesz rzucić okiem na aplikację wiecznej usługi !

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

exec('php main.php', function (error, stdOut, stdErr) {
    // do what you want!
});
keupsonite
źródło
Aby uniknąć wywołań zwrotnych, do szybkich poleceń możesz użyć execSync .
Dan Dascalescu
5

Uwaga: te odpowiedzi pochodzą z klienta opartego na przeglądarce na serwer sieciowy oparty na systemie Unix.

Uruchom polecenie na kliencie

Zasadniczo nie możesz. Bezpieczeństwo mówi, że działa tylko w przeglądarce, a jej dostęp do poleceń i systemu plików jest ograniczony.

Uruchom ls na serwerze

Możesz użyć wywołania AJAX, aby pobrać dynamiczną stronę przekazującą parametry za pośrednictwem GET.

Należy pamiętać, że stwarza to również zagrożenie dla bezpieczeństwa, ponieważ musiałbyś zrobić coś, aby upewnić się, że haker pani Rouge nie spowoduje, że Twoja aplikacja powie uruchom: / dev / null && rm -rf / ......

W skrócie, ucieczka z JS to po prostu zły, zły pomysł ... YMMV

Wayne
źródło
Zasadniczo nie można tego robić przy użyciu różnych przeglądarek. Uważam, że tylko IE ma podpięcia do powłoki (przez WSript / ActiveX).
Justin Johnson,
3

Kolejny post na ten temat z ładnym rozwiązaniem jQuery / Ajax / PHP:

skrypty powłoki i jQuery

sierpień
źródło
3

W IE możesz to zrobić:

var shell = new ActiveXObject("WScript.Shell");
shell.run("cmd /c dir & pause");
nonozor
źródło
3

Oto proste polecenie, które wykonuje ifconfigpolecenie powłoki systemu 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
źródło
Aby uniknąć wywołań zwrotnych, możesz użyć 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);
}

Ta funkcja może być łatwo używana, na przykład:

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

exec('echo test', function(err, stdout){console.log(stdout+stdout+stdout)});
//output:
//testtesttest
AliFurkan
źródło
1

Z nashornem możesz napisać taki skrypt:

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

i uruchom go:

jjs -scripting each_file.js
Maciek Łoziński
źródło
0

Jeśli używasz npm, możesz użyć pakietu shelljs

Żeby zainstalować: npm install [-g] shelljs

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

Zobacz więcej: https://www.npmjs.com/package/shelljs

Emma
źródło