Sunil Kumar Sahoo
Sunil Kumar Sahoo

Reputation: 53647

How to execute shell commands in JavaScript

I want to write a JavaScript function which will execute the system shell commands (ls for example) and return the value.

How do I achieve this?

Upvotes: 231

Views: 721641

Answers (17)

GutenYe
GutenYe

Reputation: 3389

For an easy way to handle shell commands, you might find the Zurk library very convenient. Here’s a simple example:

import { $ } from 'zurk'
const result await $`echo hello`
console.log(result.toString())

If you’re looking for something more powerful to write shell scripts in JavaScript, consider using Script.js.

Upvotes: 0

Wayne
Wayne

Reputation: 3435

Note: These answers are from a browser-based client to a Unix-based web server.

Run a command on the client

You essentially can't. Security says only run within a browser and its access to commands and filesystem is limited.

Run 'ls' on the server

You can use an Ajax call to retrieve a dynamic page, passing in your parameters via a GET.

Be aware that this also opens up a security risk as you would have to do something to ensure that Mrs rouge hacker does not get your application to say run: /dev/null && rm -rf / ...

So in a nutshell, running from JavaScript is just a bad, bad idea... your mileage may vary.

Upvotes: 8

Matt
Matt

Reputation: 44058

This depends entirely on the JavaScript environment.

For example, in Windows Scripting, you do things like:

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

Upvotes: 35

Michele Giammarini
Michele Giammarini

Reputation: 34

Js file

var oShell = new ActiveXObject("Shell.Application");
oShell.ShellExecute("E:/F/Name.bat","","","Open","");

Bat file

powershell -Command "& {ls | Out-File -FilePath `E:F/Name.txt}"`

Js file run with node namefile.js

const fs = require('fs')

fs.readFile('E:F/Name.txt', (err, data) => {
if (err) throw err;

console.log(data.toString());
})

You can also do everything in one solution with an asynchronous function. Directly there could be security problems.

Upvotes: 0

Josh
Josh

Reputation: 2077

I'll answer assuming that when the asker said "Shell Script" he meant a Node.js backend JavaScript. Possibly using commander.js to use frame your code :)

You could use the child_process module from node's API. I pasted the example code below.

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

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

Upvotes: 193

priyanshu bindal
priyanshu bindal

Reputation: 346

const fs = require('fs');

function ls(startPath) {
    fs.readdir(startPath, (err, entries) => {
        console.log(entries);
    })
}

ls('/home/<profile_name>/<folder_name>')

The startPath used here is in reference with debian distro

Upvotes: 0

Dan Dascalescu
Dan Dascalescu

Reputation: 151916

I don't know why the previous answers gave all sorts of complicated solutions. If you just want to execute a quick command like ls, you don't need async/await or callbacks or anything. Here's all you need - 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);

For error handling, add a try/catch block around the statement.

If you're running a command that takes a long time to complete, then yes, look at the asynchronous exec function.

Upvotes: 147

Nagev
Nagev

Reputation: 13207

As far as I can tell, there is no built-in function, method or otherwise, in the official ECMAScript specification to run an external process. That said, extensions are allowed, see this note from the spec, for example:

NOTE Examples of built-in functions include parseInt and Math.exp. A host or implementation may provide additional built-in functions that are not described in this specification.

One such "host" is Node.js which has the child_process module. Let's try this code to execute the Linux shell command ps -aux, saved in runps.js, based on the child_process documentation:

const { spawn } = require('child_process');
const ps = spawn('ps', ['-aux']);

ps.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ps.stderr.on('data', (data) => {
  console.error(`stderr: ${data}`);
});

ps.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});

Which produces the following example output, running it in docker:

$ docker run --rm -v "$PWD":/usr/src/app -w /usr/src/app node:17-bullseye node ./runps.js
stdout: USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.8 319312 33888 ?        Ssl  11:08   0:00 node ./runps.js
root          13  0.0  0.0   6700  2844 ?        R    11:08   0:00 ps -aux

child process exited with code 0

The thing I like about this module, is that it's included with the Node.js distribution, no npm install ... needed.

If you search the Node.js code in github for spawn you will find references to the implementation in C or C++ in the engine. Modern browsers like Firefox and Chrome would be reluctant to extend JavaScript with such features, for obvious security reasons, even if the underlying engine such as V8 supports it.

On that note, it's better not to run our container as root, let's try the above example again, adding a random user this time.

$ docker run --rm -u 7000 -v "$PWD":/usr/src/app -w /usr/src/app node:17-bullseye node ./runps.js
stdout: USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
7000           1  5.0  0.8 319312 33812 ?        Ssl  11:19   0:00 node ./runps.js
7000          13  0.0  0.0   6700  2832 ?        R    11:19   0:00 ps -aux

child process exited with code 0

Of course that's better but not enough. If this approach is used at all, more precautions must be taken, such as ensuring that no arbitrary user commands can be executed.

Windows 10

My version of Windows 10 still has Windows Script Host which can run JScript on the console with the wscript.exe or cscript.exe programs, i.e. no browser needed. To try it out you can open a PowerShell Windows Terminal. Save the following code into a file which you can call shell.js:

WScript.StdOut.WriteLine("Hallo, ECMAScript on Windows!");
WScript.CreateObject("WScript.Shell").run("C://Windows//system32//mspaint.exe");

And on the command line, run:

cscript .\shell.js

Which shows the following and opens Paint:

Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.

Hallo, ECMAScript on Windows!

Other variations exist. Find the documentation applicable to your preferred JavaScript runtime environment.

Upvotes: 4

Emma
Emma

Reputation: 171

If you are using npm you can use the shelljs package

To install: npm install [-g] shelljs

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

See more: https://www.npmjs.com/package/shelljs

Upvotes: 3

AliFurkan
AliFurkan

Reputation: 557

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

This function can be easily used like:

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

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

Upvotes: 9

Dana
Dana

Reputation: 2739

In a nutshell:

// 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");

Upvotes: 21

Anup Panwar
Anup Panwar

Reputation: 293

Here is simple command that executes ifconfig shell command of Linux

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

Upvotes: 5

keupsonite
keupsonite

Reputation: 399

With NodeJS is simple like that! And if you want to run this script at each boot of your server, you can have a look on the forever-service application!

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

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

Upvotes: 8

Maciej Łoziński
Maciej Łoziński

Reputation: 883

With nashorn you can write a script like this:

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

and run it:

jjs -scripting each_file.js

Upvotes: 1

Mirek Rusin
Mirek Rusin

Reputation: 19462

...few year later...

ES6 has been accepted as a standard and ES7 is around the corner so it deserves updated answer. We'll use ES6+async/await with nodejs+babel as an example, prerequisites are:

Your example foo.js file may look like:

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

Make sure you have babel:

npm i babel-cli -g

Install latest preset:

npm i babel-preset-latest

Run it via:

babel-node --presets latest foo.js

Upvotes: 75

nonozor
nonozor

Reputation: 934

In IE, you can do this :

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

Upvotes: 2

August
August

Reputation: 708

Another post on this topic with a nice jQuery/Ajax/PHP solution:

shell scripting and jQuery

Upvotes: 2

Related Questions