วิธีดำเนินการคำสั่งเชลล์ใน Javascript


127

ฉันต้องการเขียนฟังก์ชัน JavaScript ซึ่งจะดำเนินการคำสั่งเชลล์ระบบ (lsตัวอย่าง) และส่งคืนค่า

ฉันจะบรรลุเป้าหมายนี้ได้อย่างไร?


4
คุณต้องการเรียกใช้คำสั่งนี้บนไคลเอนต์หรือบนเซิร์ฟเวอร์ที่ไหน
ม.ค. Hančič

คุณใช้ระบบปฏิบัติการใด
Anderson Green

นี่คือบทแนะนำเกี่ยวกับวิธีการใช้ node.js สำหรับเชลล์สคริปต์: dreamsyssoft.com/javascript-shell-scripting/shell-tutorial.php
Rocky Pulley

7
ทำไมคุณถึงเลือกคำตอบที่ไม่ชอบมากที่สุดเป็นคำตอบที่ดีที่สุด o.0
André Levy

โปรดระบุประเภทของจาวาสคริปต์ให้ชัดเจนยิ่งขึ้น สิ่งนี้เป็นไปได้บนจาวาสคริปต์ฝั่งเซิร์ฟเวอร์ แต่เป็นไปไม่ได้บนจาวาสคริปต์ฝั่งไคลเอ็นต์
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
ยกเว้นสิ่งเดียว คุณจะได้รับข้อผิดพลาด "child is not a function" call to exec () เรียกใช้คำสั่ง - ไม่จำเป็นต้องเรียก child () น่าเสียดายที่การเรียกกลับไม่ได้ถูกเรียกเมื่อใดก็ตามที่กระบวนการลูกมีสิ่งที่จะส่งออก - จะเรียกเฉพาะเมื่อกระบวนการลูกออก บางครั้งก็ไม่เป็นไรและบางครั้งก็ไม่เป็นเช่นนั้น
John Deighan

2
เพื่อหลีกเลี่ยงการเรียกกลับคุณสามารถใช้execSync
Dan Dascalescu

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
Dan Dascalescu

ไม่มีใครถามหาโซลูชัน Node.js มันพูดเฉพาะ JavaScript
Virus721

43

ฉันไม่รู้ว่าทำไมคำตอบก่อนหน้านี้จึงให้คำตอบที่ซับซ้อนทุกประเภท หากคุณต้องการดำเนินการคำสั่งด่วนเช่นlsคุณไม่จำเป็นต้อง async / await หรือ callbacks หรืออะไรเลย นี่คือทั้งหมดที่คุณต้องการ - 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");

18
เป็นไปได้ไหมที่จะทำสิ่งเดียวกันในระบบปฏิบัติการที่คล้าย Unix เช่น Linux?
Anderson Green

เราจะรันคำสั่งนี้ได้อย่างไร: route print -4 | หา \ "TAP-Windows Adapter \" ?? ฉันพยายาม แต่กลับไม่มีอะไรเลย
ikel

1
นั่นคือสิ่งที่ฉันกำลังมองหา มันน่ารำคาญที่ทุกคนพูดถึง Node.js ของพวกเขา ใครถามหา Node.js ที่นี่? ไม่มีใครทำ
Virus721

จะใช้งานได้หรือไม่ถ้า JavaScript อยู่ในเบราว์เซอร์
Ali Sajjad

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


5
ดูเหมือนว่าจะมีการบีบอัดเว็บเบราว์เซอร์ที่กำลังทำงานอยู่ แต่ผู้ใช้ควรตระหนักว่า JavaScript เป็นภาษาสคริปต์เชลล์ของ Windows ที่ถูกต้องอย่างสมบูรณ์แบบ
Craig

6

ด้วย NodeJS ก็ง่ายเช่นนั้น! และหากคุณต้องการเรียกใช้สคริปต์นี้ในการบูตเซิร์ฟเวอร์แต่ละครั้งคุณสามารถดูแอปพลิเคชันบริการตลอดไปได้ !

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

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

การเรียกกลับหลีกเลี่ยงสำหรับคำสั่งอย่างรวดเร็วคุณสามารถใช้execSync
Dan Dascalescu

5

หมายเหตุ: คำตอบเหล่านี้มาจากไคลเอนต์ที่ใช้เบราว์เซอร์ไปจนถึงเว็บเซิร์ฟเวอร์ที่ใช้ Unix

รันคำสั่งบนไคลเอนต์

โดยพื้นฐานแล้วคุณทำไม่ได้ ความปลอดภัยระบุว่าทำงานภายในเบราว์เซอร์เท่านั้นและการเข้าถึงคำสั่งและระบบไฟล์มี จำกัด

รัน ls บนเซิร์ฟเวอร์

คุณสามารถใช้การเรียก AJAX เพื่อดึงเพจไดนามิกที่ส่งผ่านพารามิเตอร์ของคุณผ่าน GET

โปรดทราบว่านี่เป็นการเปิดความเสี่ยงด้านความปลอดภัยเช่นกันเนื่องจากคุณต้องทำบางอย่างเพื่อให้แน่ใจว่าแฮ็กเกอร์ mrs rouge ไม่ได้รับแอปพลิเคชันของคุณที่จะบอกว่า run: / dev / null && rm -rf / ......

ดังนั้นในช่วงเวลาสั้น ๆ การวิ่งจาก JS เป็นเพียงความคิดที่ไม่ดีและไม่ดี .... YMMV


โดยพื้นฐานแล้วคุณไม่สามารถใช้งานข้ามเบราว์เซอร์ได้ ฉันเชื่อว่ามีเพียง IE เท่านั้นที่มี hooks ในเชลล์ (ผ่าน WSript / ActiveX)
Justin Johnson



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

ฟังก์ชันนี้สามารถใช้งานได้ง่ายเช่น:

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

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

1

ด้วยnashornคุณสามารถเขียนสคริปต์ดังนี้:

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

และเรียกใช้:

jjs -scripting each_file.js

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.