如何在JavaScript中执行shell命令

我想编写一个JavaScript函数,该函数将执行系统shell命令(例如,__abc0)并返回值。

我如何实现这一点?

597783 次浏览

这完全取决于JavaScript环境。请详细说明。

例如,在Windows脚本中,您可以执行以下操作:

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

简而言之:

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

注意:这些答案是从基于浏览器的客户端到基于UNIX的Web服务器。

在客户端上运行命令

你基本上不能。安全部门表示只能在浏览器中运行,并且对命令和文件系统的访问受到限制。

在服务器上运行ls

您可以使用Ajax调用来检索动态页面,并通过GET传递参数。

请注意,这也会带来安全风险,因为您必须采取措施确保Mrs Rouge Hacker不会让您的应用程序说run:/dev/null&;&;。RM-RF/.。

所以在一个疯子,从JS运行只是一个坏主意,坏主意..YMMV

关于这个主题的另一篇文章,有一个很好的jQuery/Ajax/PHP解决方案:

Shell脚本和jQuery

我会回答,假设当提问者说";shell脚本";他指的是Node.JS后端JavaScript.可能使用指挥官.JS来使用您的代码框架:)

您可以使用节点API中的儿童_进程模块。我粘贴了下面的示例代码。

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

希望这能有所帮助!

在IE中,您可以执行以下操作:

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

...几年后..

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

确保你有巴别塔:

npm i babel-cli -g

安装最新预设:

npm i babel-preset-latest

通过以下方式运行:

babel-node --presets latest foo.js

下面是一个简单的命令,执行Linux的ifconfig shell命令

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

使用纳绍恩,您可以编写如下脚本:

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

并运行它:

jjs -scripting each_file.js

NodeJS就是这么简单! 如果您希望在每次引导服务器时运行此脚本,可以查看永远服务应用程序。

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


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

我不知道为什么以前的答案给出了各种复杂的解决方案。如果您只想执行一个快速命令,如__abc0,您不需要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函数。

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

如果您正在使用NPM,则可以使用shelljs包。

安装:npm install [-g] shelljs

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

查看更多:https://www.npmjs.com/package/shelljs

据我所知,在官方的ECMAScript规范中没有运行外部进程的内置函数、方法或其他。也就是说,扩展是允许的,请参见规范中的这张纸条,例如:

注意:内置函数的示例包括parseInt和Math.exp. 主机或实现可以提供附加的内置函数,其 在本说明书中没有描述。

一个这样的“主机”是具有child_process模块的node.JS。让我们试着用这段代码根据__abc4来执行保存在__abc2中的Linux shell命令__abc1:

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

码头工人中运行,将生成以下示例输出:

$ 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

我喜欢这个模块的一点是,它包含在Node.JS发行版中,不需要npm install ...

如果您在GitHub中的Node.JS代码中搜索spawn,您将在引擎中找到对C或C++中的实施的引用。出于明显的安全原因,像火狐和Chrome这样的现代浏览器将不愿意用这样的功能来扩展JavaScript,即使像V8这样的底层引擎支持它。

关于这一点,最好不要以root身份运行我们的容器,让我们再次尝试上面的示例,这次添加一个随机用户

$ 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

这当然更好,但还不够。如果使用这种方法,则必须采取更多的预防措施,例如确保不能执行任意用户命令。

Windows 10

我的Windows 10版本仍然有Windows脚本宿主,它可以在控制台上使用wscript.execscript.exe程序运行JScript,也就是说,不需要浏览器。要尝试它,您可以打开一个PowerShellWindows终端。将以下代码保存到一个文件中,您可以将该文件称为shell.js

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

并在命令行上运行:

cscript .\shell.js

显示以下内容并打开“画图”:

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


Hallo, ECMAScript on Windows!

还存在其他变化。查找适用于您首选的JavaScript运行时环境的文档。

const fs = require('fs');


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


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

这里使用的StartPath与Debian发行版有关