234

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?

4
  • 5
    where would you like to execute this command, on the client or on the server? Commented Dec 10, 2009 at 10:56
  • 8
    Why did you choose the most disliked answer as the best answer? o.0 Commented Jun 27, 2018 at 0:02
  • For anyone who wants to execute a command on button click, check the next.js way here: stackoverflow.com/questions/71646984/… Commented Mar 29, 2022 at 20:19
  • So it is really difficult to execute commands like cd or pwd in browser JavaScript? On the client, of course? Commented Sep 17, 2024 at 14:40

18 Answers 18

193

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);
        }
    });
Sign up to request clarification or add additional context in comments.

5 Comments

Except for one thing. You'll get the error "child is not a function". The call to exec() executes the command - no need to call child(). Unfortunately, the callback isn't called whenever the child process has something to output - it is called only when the child process exits. Sometimes that's OK and sometimes it's not.
To avoid callbacks, you can use execSync.
Who talked about a browser ? It only says JavaScript, nothing more.
@Josh How to pass credentials here (user name and password)?
Who talked about node.js? It only says JavaScript , nothing more.
148

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.

6 Comments

Does execSync works with Mac, Linux and Windows commands?
Confirmed for windows. Also, I see that there's a shell option for specifying "Shell to execute the command with." Default: '/bin/sh' on Unix, process.env.ComSpec on Windows.
Please do not use synchronous external operations, because your server will not be able to serve other requests until it is finished.
Is this appropriate for commands like cd and pwd?
@DavidSpector yes it is (I just tested in PureScript's bindings to execSync), however do note that each execSync launches its own shell, so your cd's only affect the code being run inside that execSync. I.e. you can do something like execSync("cd foo && ls"), but it isn't the same as running separately execSync("cd foo") and then execSync("ls").
|
75

...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

3 Comments

If you only need to execute a quick command, all the async/await is overkill. You can just use execSync.
No one asked for a Node.js solution. It only says JavaScript.
@Virus721: in which JavaScript runtime do you want to execute a shell command?
35

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

4 Comments

Is it possible to do the same thing in a Unix-like operating system such as Linux?
That's what I was looking for. It's annoying all those people talking about their Node.js. Who asked for Node.js here ? No one did.
Would you know how to get some result (say, exit code), of the newly run command?
@sighclone I answered this nearly 14 years ago, can't say I've kept up with WScript. But the docs say the Run() method returns the exit code. vbsedit.com/html/6f28899c-d653-4555-8a59-49640b0e32ea.asp
21

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

2 Comments

There seems to be a lot of hand-wringing over which web browser this is running in, but folks should realize that JavaScript is also a perfectly valid Windows shell scripting language.
9
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

1 Comment

For some reason the commands are executed from the end. For example, the commands exec('echo 1'); exec('echo 2'); exec('echo 3'); exec('echo 4'); will lead to the conclusion 4 3 2 1
9

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.

2 Comments

You essentially can't in a cross-browser manner. I believe only IE has hooks into the shell (via WSript/ActiveX).
All the high vote answers assume it's run in a non-browser context, e.g. Node. The right thing is to clarify the question, not this answer.
8

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

2 Comments

To avoid callbacks, for quick commands you can use execSync.
what if want to run sudo mysql .?? is it possible ?? if yes, how the password, it is going to ask after this command.
5

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

1 Comment

To avoid callbacks, you can use execSync.
4

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.

Comments

3

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

Comments

2

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

shell scripting and jQuery

1 Comment

the question specifies javascript.
2

In IE, you can do this :

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

1 Comment

ActiveXObject is available only for IE browser.
1

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

Comments

0
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

Comments

0

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.

Comments

0

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.

Comments

0

Run bash commands from BunJs, the latest JavaScript runtime environment similar to NodeJs:

import { $ } from "bun";
const myFileName = "file1";
const output = await $`ls -l ${myFileName}`.text();
console.log(output);

https://bun.sh/guides/runtime/shell

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.