नोड.जेएस सिस्टम कमांड को सिंक्रोनाइज़ करता है


171

मुझे नोड.जेएस फ़ंक्शन की आवश्यकता है

result = execSync('node -v');

जो दी गई कमांड लाइन को समकालिक रूप से निष्पादित करेगा और उस कमांड टेक्स्ट द्वारा सभी stdout'ed को लौटाएगा।

ps। सिंक गलत है। मुझे पता है। सिर्फ निजी इस्तेमाल के लिए।

अपडेट करें

अब हमारे पास mgutz का समाधान है जो हमें बाहर निकलने का कोड देता है, लेकिन स्टडआउट नहीं! अभी भी अधिक सटीक उत्तर की प्रतीक्षा है।

अपडेट करें

mgutz ने अपने उत्तर को अपडेट किया और समाधान यहां है :)
इसके अलावा, जैसा कि dgo.a ने उल्लेख किया है, स्टैंड-अलोन मॉड्यूल निष्पादन-सिंक है

अद्यतन 2014-07-30

शेलजेएस परिवाद आया। विचार करें कि यह अभी के लिए सबसे अच्छा विकल्प है।


अद्यतन 2015-02-10

अंत में! NodeJS 0.12 execSyncमूल रूप से समर्थन करता है।
आधिकारिक डॉक्स देखें


26
अपने आप को मूर्ख मत बनने दो, सिंक गलत नहीं है ... NodeJS में आपके सभी कोड को तब तक सिंक्रोनाइज़ किया जाता है जब तक कि आप स्पष्ट रूप से एक एसिंक्स पद्धति को नहीं कहते हैं ... अगर सब कुछ एसिंक्रोनस तरीके से किया जाता तो कभी भी कुछ भी नहीं होता। इसके अलावा, अतुल्यकालिक तरीकों को प्राथमिकता देने का मतलब यह नहीं है कि आपकी लंबी गणना आपके सर्वर को अवरुद्ध नहीं करेगी। यह एक विकल्प है। नोड के निर्माताओं ने एसिंक्स वालों के साथ समकालिक फाइल सिस्टम विधियां प्रदान करने के लिए चुना है जो सिर्फ यह दिखाने के लिए जाता है कि उन लोगों के लिए भी एक जगह है।
प्रवाह

2
आप जिस "यूनिक्स शेल एमुलेशन लाइब्रेरी" के बारे में बात कर रहे हैं, वह कहाँ मिल सकती है?
फ्लोरियन

@Florian वह इसका मतलब है ShellJS
XST

जवाबों:


153

Node.js (संस्करण 0.12 से - थोड़ी देर के लिए) समर्थन करता है execSync:

child_process.execSync(command[, options])

अब आप सीधे ऐसा कर सकते हैं:

const execSync = require('child_process').execSync;
code = execSync('node -v');

और यह वही होगा जो आप उम्मीद करते हैं। (मूल प्रक्रिया के लिए i / o परिणामों को पाइप करने के लिए चूक)। ध्यान दें कि spawnSyncअब आप भी कर सकते हैं।


6
10 घंटे की निराशा के बाद। धन्यवाद DUDE
टॉम देव

मैं इस उपप्रकार से कैसे काट सकता हूं?
जूलियनसोटो


54

निष्कासन पुस्तकालय देखें ।

नोड- ffi के साथ करना काफी आसान है । मैं सर्वर प्रक्रियाओं के लिए सिफारिश नहीं करूंगा, लेकिन सामान्य विकास उपयोगिताओं के लिए यह काम हो जाता है। पुस्तकालय स्थापित करें।

npm install node-ffi

उदाहरण लिपि:

var FFI = require("node-ffi");
var libc = new FFI.Library(null, {
  "system": ["int32", ["string"]]
});

var run = libc.system;
run("echo $USER");

[संपादित जून 2012: STDOUT कैसे प्राप्त करें]

var lib = ffi.Library(null, {
    // FILE* popen(char* cmd, char* mode);
    popen: ['pointer', ['string', 'string']],

    // void pclose(FILE* fp);
    pclose: ['void', [ 'pointer']],

    // char* fgets(char* buff, int buff, in)
    fgets: ['string', ['string', 'int','pointer']]
});

function execSync(cmd) {
  var
    buffer = new Buffer(1024),
    result = "",
    fp = lib.popen(cmd, 'r');

  if (!fp) throw new Error('execSync error: '+cmd);

  while(lib.fgets(buffer, 1024, fp)) {
    result += buffer.readCString();
  };
  lib.pclose(fp);

  return result;
}

console.log(execSync('echo $HOME'));

2
आप वास्तव में stdoutइस से भेजे गए कुछ भी प्राप्त करने के बारे में कैसे जाएंगे ? सभी मैं प्राप्त कर सकते हैं प्रक्रिया से बाहर निकलें कोड
मार्क Kahn

@ घड़ियाँ: मुझे लगता है कि async यह बेहतर होगा। ( इवो ​​का जवाब )
poverb

@pvorb - हाँ, सिवाय जब आप async उपयोग नहीं कर सकते हैं :)
मार्क काह्न

1
हर नाखून के लिए एसिंक हथौड़ा का उपयोग न करने के वैध कारण हैं। उदाहरण के लिए, टेम्पलेट इंजन एक्सप्रेस 3 में async हैं और सहायक कार्यों (स्थानीय लोगों) को सिंक्रोनस करने की आवश्यकता है। क्या होगा अगर उन सहायक कार्यों को मक्खी पर अतुल्यकालिक रूप से कम फ़ाइलों को संकलित करने की आवश्यकता है?
२०:०५ पर एमगुट्टज

8
मुझे आश्चर्य है कि यह सरल execSyncका हिस्सा क्यों नहीं है child_process। मुझे लगता है, यह होना चाहिए।
माइकल Härtl

31

शेलजेएस मॉड्यूल का उपयोग करें ।

कार्यकारी कॉलबैक उपलब्ध कराने के बिना कार्य करते हैं।

उदाहरण:

var version = exec('node -v').output;

2
ध्यान दें कि लेखन के समय, डॉक्स उल्लेख करते हैं कि तुल्यकालिक exec()सीपीयू लंबी प्रक्रियाओं के लिए गहन है।
अराम कोचरन

1
विकल्प, {साइलेंट: ट्रू} की कुंजी है
निक

1
यह कुछ (छोटे सिंटैक्स प्रदान करने के अलावा) यह नहीं करता है? const execSync = require('child_process').execSync; code = execSync('node -v');
user2503764

23

नोड में प्रवाह नियंत्रण के लिए एक उत्कृष्ट मॉड्यूल है । इसे asyncblock कहा जाता है । यदि किसी फ़ंक्शन में कोड लपेटना आपके मामले के लिए ठीक है, तो निम्नलिखित नमूने पर विचार किया जा सकता है:

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

asyncblock(function (flow) {
    exec('node -v', flow.add());
    result = flow.wait();
    console.log(result);    // There'll be trailing \n in the output

    // Some other jobs
    console.log('More results like if it were sync...');
});

1
उन्होंने स्पष्ट रूप से सिंक संस्करण के बारे में पूछा, प्रवाह पुस्तकालयों को नियंत्रित नहीं किया।
एलेक्सी पेत्रुशिन

22
@AlexeyPetrushin यहां प्रत्येक प्रश्न एक लक्ष्य के बारे में है, न कि इसे प्राप्त करने के विशेष तरीके के बारे में। हालांकि downvoting के लिए धन्यवाद।
नब

1
इसके अलावा, यह विंडोज उपयोगकर्ताओं के लिए एक बहुत ही उपयोगी उत्तर है; विंडोज पर स्थापित exec-syncया ffiविशाल ओवरहेड (VC ++, SDKs, पायथन, आदि) है, लेकिन यह हल्का है।
मेंढक

10

यह Node.js में संभव नहीं है, दोनों को जमीन से बनाया गया था child_process.spawnऔर child_process.execइसे async किया गया था।

विवरण के लिए देखें: https://github.com/ry/node/blob/master/lib/child_process.js

यदि आप वास्तव में इस अवरोधन को प्राप्त करना चाहते हैं, तो एक कॉलबैक में बाद में होने वाली सभी चीज़ों को रखें, या एक अवरुद्ध फैशन में इसे संभालने के लिए अपनी खुद की कतार बनाएं , मुझे लगता है कि आप इस कार्य के लिए Async.js का उपयोग कर सकते हैं ।

या, यदि आपके पास खर्च करने के लिए बहुत अधिक समय है, तो Node.js में स्वयं को हैक करें।


12
अजीब है क्योंकि फ़ाइल सिस्टम मॉड्यूल में सिंक्रोनस कॉल हैं। क्यों नहीं किया गया अमल?
अल्फ्रेड

4
@ उपलब्ध कराए गए सिंक FS कॉल मुख्य रूप से प्रोग्राम स्टार्ट पर कॉन्फिग को लोड करने के लिए हैं।
Ivo वेटज़ेल

3
@IvoWetzel - tisk tisk ... क्या हमने कभी नहीं कहा कि कुछ असंभव है? ;) नीचे मेरा समाधान देखें।
मार्कस पोप

1
@IvoWetzel "सिंक FS कॉल ..." - सही है, और कभी-कभी आप चाहते हैं, कहे, प्रोग्राम शुरू होने पर कुछ संकलन करने के लिए एक आदेश जारी करें और पूरा होने पर जारी रखें। - यह देखते हुए सिंक एफएस कॉल नहीं हैं, सिंक निष्पादन नहीं है एक निरीक्षण की तरह लग रहा है। मैं सभी अतुल्यकालिक के लिए हूँ, लेकिन तुल्यकालिक इसके पेशेवरों और उपयोग के मामले हैं। यह निश्चित रूप से एक विवेकपूर्ण तरीके से उपयोग करना चाहिए।
प्रवाह

Async ठीक है, लेकिन अगर WidgetB WidgetA के अंतिम परिणामों पर निर्भर करता है, तो दुनिया के सभी Async को काम नहीं मिलेगा। कभी-कभी प्रक्रियाओं को समकालिक होना पड़ता है। एसिंक्रोनस रूप से खाना पकाने की कोशिश करें। ;)
लॉयड सार्जेंट

9

यह सबसे आसान तरीका है जो मैंने पाया:

निष्पादित -सिंक : https://github.com/jeremyfa/node-exec-sync
(
निष्पादित करने के लिए भ्रमित नहीं होना।) शेल कमांड को सिंक्रोनाइज़ करना। माइग्रेशन स्क्रिप्ट, क्लि प्रोग्राम के लिए इसका उपयोग करें, लेकिन नियमित सर्वर कोड के लिए नहीं।

उदाहरण:

var execSync = require('exec-sync');   
var user = execSync('echo $USER');
console.log(user);

7

बस यह जोड़ने के लिए कि भले ही कुछ usecases हैं जहाँ आपको उनका उपयोग करना चाहिए, spawnSync/ execFileSync/ execSyncइन नोड्स में नोड्स जोड़े गए थे: https://github.com/joyent/node/compare/d58c206862dc...88df2676748e


इसका मतलब है कि हम इसे v0.12 बॉक्स से बाहर करने जा रहे हैं?
विच्छेदित

@ संतुष्ट किया गया हाँ: strongloop.com/strongblog/…
बालूपटन

5

आप तंतुओं का उपयोग करके इसे प्राप्त कर सकते हैं। उदाहरण के लिए, मेरी कॉमन नोड लाइब्रेरी का उपयोग करते हुए , कोड इस तरह दिखेगा:

result = require('subprocess').command('node -v');

3

मुझे "synchronous"कॉलबैक फ़ंक्शन के अंत में सामान को लागू करने की आदत है । बहुत अच्छा नहीं है, लेकिन यह काम करता है। यदि आपको कमांड लाइन के अनुक्रम को कार्यान्वित करने की आवश्यकता है, तो आपको execकुछ नामित फ़ंक्शन में लपेटने और इसे पुन: कॉल करने की आवश्यकता है। यह पैटर्न मेरे लिए प्रयोग करने योग्य प्रतीत होता है:

SeqOfExec(someParam);

function SeqOfExec(somepParam) {
    // some stuff
    // .....
    // .....

    var execStr = "yourExecString";
    child_proc.exec(execStr, function (error, stdout, stderr) {
        if (error != null) {
            if (stdout) {
                throw Error("Smth goes wrong" + error);
            } else {
                // consider that empty stdout causes
                // creation of error object
            }
        }
        // some stuff
        // .....
        // .....

        // you also need some flag which will signal that you 
        // need to end loop
        if (someFlag ) {
            // your synch stuff after all execs
            // here
            // .....
        } else {
            SeqOfExec(someAnotherParam);
        }
    });
};

3

मुझे भी इसी तरह की समस्या थी और मैंने इसके लिए एक नोड एक्सटेंशन लिखना शुरू किया। आप गिट रिपॉजिटरी देख सकते हैं। यह खुला स्रोत और मुफ्त है और यह सब अच्छा सामान है!

https://github.com/aponxi/npm-execxi

ExecXI एक नोड एक्सटेंशन है जो C ++ में शेल कमांड को निष्पादित करने के लिए एक-एक करके लिखा जाता है, कमांड के आउटपुट को कंसोल में रियल-टाइम में आउटपुट करता है। वैकल्पिक जंजीर, और अप्रकाशित तरीके मौजूद हैं; इसका अर्थ है कि आप कमांड के विफल होने (जंजीर) हो जाने के बाद स्क्रिप्ट को रोकना चुन सकते हैं, या आप जारी रख सकते हैं जैसे कि कुछ भी नहीं हुआ है!

उपयोग निर्देश ReadMe फ़ाइल में हैं । पुल अनुरोध या मुद्दों को प्रस्तुत करने के लिए स्वतंत्र महसूस करो!

संपादित करें: हालांकि यह अभी तक स्टडआउट वापस नहीं करता है ... बस उन्हें वास्तविक समय में आउटपुट करता है। यह अब करता है।खैर, मैंने आज ही इसे जारी किया। शायद हम उस पर निर्माण कर सकते हैं।

वैसे भी, मुझे लगा कि यह उल्लेख के लायक है।


यह वास्तव में वो ही है जो मैं ढूंढ़ रहा हूँ। इसे बनाने के लिए समय देने के लिए धन्यवाद।
थीलफ्रेड्स

केवल एक चीज जो मुझे समझ में नहीं आई है और वह है विभिन्न नोडज संस्करणों के लिए बिल्ड कॉन्फ़िगरेशन। मुझे लगता है कि मैंने इसे नोड 0.8 ( travis-ci.org/aponxi/npm-execxi/builds/5248535 ) पर लिखा था, जब तक कि npm installसफल नहीं होता (प्लगइन संकलन के रूप में दूसरे शब्दों में), तो उत्पादन के लिए जाना अच्छा है। विभिन्न नोडज संस्करणों को लक्षित करने के अलावा, मैं कहूंगा कि यह उत्पादन के लिए तैयार है, या यह बहुत स्थिर है। अगर कोई बग है तो आप एक पुल अनुरोध में भेज सकते हैं या एक मुद्दे को github पर भेज सकते हैं :)
लोगान

1

आप नोडज में तुल्यकालिक खोल संचालन कर सकते हैं जैसे:

var execSync = function(cmd) {

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

    //for linux use ; instead of &&
    //execute your command followed by a simple echo 
    //to file to indicate process is finished
    exec(cmd + " > c:\\stdout.txt && echo done > c:\\sync.txt");

    while (true) {
        //consider a timeout option to prevent infinite loop
        //NOTE: this will max out your cpu too!
        try {
            var status = fs.readFileSync('c:\\sync.txt', 'utf8');

            if (status.trim() == "done") {
                var res = fs.readFileSync("c:\\stdout.txt", 'utf8');
                fs.unlinkSync("c:\\stdout.txt"); //cleanup temp files
                fs.unlinkSync("c:\\sync.txt");
                return res;
            }
        } catch(e) { } //readFileSync will fail until file exists
    }

};

//won't return anything, but will take 10 seconds to run
console.log(execSync("sleep 10")); 

//assuming there are a lot of files and subdirectories, 
//this too may take a while, use your own applicable file path
console.log(execSync("dir /s c:\\usr\\docs\\"));

EDIT - यह उदाहरण विंडोज़ वातावरण के लिए है, यदि आवश्यक हो तो अपने स्वयं के लिनक्स जरूरतों के लिए समायोजित करें


हां, और जितनी तेजी से आपका सीपीयू सम्भवत: सम्मन कर सकता है ... लेकिन हे जब आपको कुछ बुराई करने के लिए "शैतान" की जरूरत है, तो क्या आपका आदमी सही है?
मार्कस पोप

ठीक है, यह शुद्ध बुराई है, लेकिन भयानक है। मुझे एक फाइलसिस्टम ईवेंट ब्राउजर.ऑन ('रजिस्टर') को संभालने के लिए इसकी आवश्यकता थी, जिसमें कॉलबैक नहीं था। मेरा दिन बचाया!
रॉबर्ट गोल्ड

क्या आप बता सकते हैं कि यह जावास्क्रिप्ट इंजन पर क्यों काम करता है? जबकि लूप को एक ही टिक पर असीम रूप से निष्पादित नहीं किया जाना चाहिए, जबकि अगले एक पर निष्पादित होता है?
बैडंक

व्यस्त प्रतीक्षा द्वारा सीपीयू को अधिकतम करना खराब डिजाइन है।
लुई

@ लुई-डोमिनिकडुबे ज़रूर, लेकिन वास्तव में कोई विकल्प नहीं है जो कि किसी तीसरे पक्ष के स्रोत पर निर्भर नहीं करता है जो कि संभावित रूप से प्रासंगिक नहीं हो सकता है। यह सीपीयू से बाहर एक सच्ची अधिकतम कमाई भी नहीं है क्योंकि OS नोडज प्रक्रिया को पूरी प्राथमिकता नहीं देगा। मुझे लगता है कि शेल ऑप्स का सिंक कार्यान्वयन क्षितिज पर या शायद यहाँ पहले से ही है।
मार्कस पोप

1

मेरे पास वास्तव में एक ऐसी स्थिति थी, जिसमें मुझे एक पैकेज के बाद एक के बाद एक कई कमांड चलाने की जरूरत थी। एक तरह से स्क्रिप्ट को प्रीइंस्टॉल्ड करना विंडोज और लिनक्स / ओएसएक्स दोनों पर काम करेगा, इसलिए मैं एक गैर-कोर मॉड्यूल पर भरोसा नहीं कर सकता था।

तो यही वह है मुझे जो मिला है:

#cmds.coffee
childproc = require 'child_process'

exports.exec = (cmds) ->
  next = ->
    if cmds.length > 0
      cmd = cmds.shift()
      console.log "Running command: #{cmd}"
      childproc.exec cmd, (err, stdout, stderr) ->
        if err? then console.log err
        if stdout? then console.log stdout
        if stderr? then console.log stderr
        next()
    else
      console.log "Done executing commands."

  console.log "Running the follows commands:"
  console.log cmds
  next()

आप इसे इस तरह से उपयोग कर सकते हैं:

require('./cmds').exec ['grunt coffee', 'nodeunit test/tls-config.js']

संपादित करें: जैसा कि बताया गया है, यह वास्तव में आउटपुट वापस नहीं करता है या आपको नोड प्रोग्राम में आदेशों के परिणाम का उपयोग करने की अनुमति देता है। इसके लिए एक अन्य विचार लाइवस्क्रिप्ट बैकस्कॉल का उपयोग करना है। http://livescript.net/


धन्यवाद, लेकिन यह एक उत्तर नहीं है क्योंकि आपका कोड श्रृंखला में अतुल्यकालिक रूप से
विच्छेदित

यदि आपको मेरे उदाहरण के अनुसार तुल्यकालिक रूप से कमांड की एक श्रृंखला निष्पादित करने की आवश्यकता है तो यह काम करेगा। मुझे लगता है कि मैं आपके प्रश्न को गलत समझ रहा हूं, क्षमा करें। मैंने जवाब में एक और विचार जोड़ा।
जेसन लिवेसे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.