2012-03-19 16 views
43

बफरिंग के बिना Node.js से एक शेल कमांड चला रहा है, मैं उस आदेश के इनपुट और आउटपुट को पुनर्निर्देशित करने के बिना के बिना Node.js, से एक शेल कमांड लॉन्च करने का प्रयास कर रहा हूं - जैसे कि शेल स्क्रिप्ट का उपयोग करके कमांड को खोलना , या रूबी के system कमांड का उपयोग कर। अगर बाल प्रक्रिया STDOUT को लिखना चाहती है, तो मैं चाहता हूं कि सीधे कंसोल पर जाएं (या रीडायरेक्ट हो जाएं, अगर मेरा नोड ऐप का आउटपुट रीडायरेक्ट किया गया हो)।आउटपुट

नोड ऐसा करने का कोई आसान तरीका प्रतीत नहीं होता है। ऐसा लगता है कि एक और प्रक्रिया चलाने का एकमात्र तरीका child_process है, जो हमेशा बाल प्रक्रिया के इनपुट और आउटपुट को पाइप पर रीडायरेक्ट करता है। मैं उन पाइपों से डेटा स्वीकार करने के लिए कोड लिख सकता हूं और इसे अपनी प्रक्रिया के एसटीडीओयूटी और एसटीडीईआरआर में लिख सकता हूं, लेकिन अगर मैं ऐसा करता हूं, तो एपीआई मुझे कुछ लचीलापन बलिदान देने के लिए मजबूर करती है।

  • शैल वाक्य रचना:

    मैं दो सुविधाओं चाहते हैं। मैं आदेशों के बीच पाइप आउटपुट करने में सक्षम होना चाहता हूं, या विंडोज बैच फ़ाइलों को चला सकता हूं।

  • असीमित आउटपुट। अगर मैं एक कंपाइलर के लिए खोल रहा हूं और यह कंपाइलर चेतावनियों के मेगाबाइट जेनरेट करना चाहता है, तो मैं चाहता हूं कि वे सभी स्क्रीन पर स्क्रॉल करें (जब तक कि उपयोगकर्ता इसका बीमार न हो जाए और Ctrl + C दबाए)।

ऐसा लगता है कि नोड मुझे उन दो विशेषताओं के बीच चुनने के लिए मजबूर करना चाहता है।

  • अगर मैं उत्पादन की एक असीमित राशि चाहता हूँ, मुझे child_process.spawn उपयोग कर सकते हैं और फिर stderr के लिए child.stdout.on('data', function(data) { process.stdout.write(data); }); और एक ही बात करते हैं, और यह गायों जब तक खुशी से पाइप डेटा घर आया हूँ। दुर्भाग्य से, spawn शैल वाक्यविन्यास का समर्थन नहीं करता है।
  • यदि मुझे खोल वाक्यविन्यास चाहिए, तो मैं child_process.exec का उपयोग कर सकता हूं। लेकिन exec मेरे लिए बाल प्रक्रिया के STDOUT और STDERR को बफर करने और अंत में उन्हें सभी को देने पर जोर देता है, और यह उन बफर (डिफ़ॉल्ट रूप से कॉन्फ़िगर करने योग्य, 200K) के आकार को सीमित करता है। मैं अभी भी on('data') घटनाओं को हुक कर सकता हूं, अगर मैं आउटपुट को जेनरेट करना चाहता हूं, लेकिन exec अभी भी डेटा को अपने बफर में जोड़ देगा। जब डेटा की मात्रा पूर्वनिर्धारित बफर आकार से अधिक हो जाती है, exec बाल प्रक्रिया को समाप्त कर देगी।

(वहाँ भी जो सबसे खराब एक लचीलापन दृष्टिकोण से दोनों दुनिया का है child_process.execFile,:। कोई खोल वाक्य रचना, लेकिन आप अभी भी उत्पादन जैसा कि आप उम्मीद की राशि टोपी है)

मुझे याद आ रही कुछ कुछ? क्या नोड में बाल प्रक्रिया को खोलने का कोई तरीका है, और इसके इनपुट और आउटपुट को पुनर्निर्देशित नहीं करता है? कुछ जो शेल सिंटैक्स का समर्थन करता है और आउटपुट की पूर्वनिर्धारित मात्रा के बाद बाहर नहीं निकलता है, जैसे कि शैल स्क्रिप्ट्स, रूबी इत्यादि में उपलब्ध है?

+1

क्या आपने कभी इसे समझ लिया था? मैं एक समान स्थिति में हूं। –

+0

एक ही मुद्दा, 'गायों के घर आने तक' धन्यवाद, इसके लिए, 10h के काम के बाद मेरा दिन बनाया – neric

उत्तर

4

मैं इसे इस्तेमाल नहीं किया है, लेकिन मैं इस पुस्तकालय को देखा है: https://github.com/polotek/procstreams

यह आप ऐसा करते हैं चाहते हैं। .out() स्वचालित रूप से प्रक्रिया के stdin/out पर पाइप करता है।

var $p = require('procstreams'); 
$p('cat lines.txt').pipe('wc -l').out(); 

यदि शैल वाक्यविन्यास का समर्थन नहीं करता है, लेकिन यह मुझे लगता है कि यह बहुत छोटा है।

var command_str = "cat lines.txt | wc -l"; 
var cmds = command_str.split(/\s?\|\s?/); 
var cmd = $p(cmds.shift()); 
while(cmds.length) cmd = cmd.pipe(cmds.shift()); 
cmd 
    .out() 
    .on('exit', function() { 
    // Do whatever 
    }); 
+3

मैंने अभी कोशिश की, और यह विंडोज बैच फ़ाइलों का समर्थन नहीं करता है, जो वास्तव में मुख्य कारण है कि मैं खोल समर्थन चाहता हूं। मूल रूप से बहुत सारे यूनिक्स टूल्स (उदा। रेक) को विंडोज़ पर बैच फाइलों का उपयोग करके कार्यान्वित किया जाता है, और मैं उन्हें नोड से इनकार करने में सक्षम होना चाहता हूं। –

+0

"समर्थन नहीं करता" से आपका क्या मतलब है? यह दुर्घटनाग्रस्त है, बैच फ़ाइल नहीं मिली, ताले और हमेशा के लिए निष्पादित करता है? – loganfsmyth

+0

'CreateProcessW: सिस्टम निर्दिष्ट फ़ाइल नहीं ढूंढ सकता है।' बैच फ़ाइल चलाने का प्रयास करते समय 'child_process.spawn' के समान त्रुटि', क्योंकि बैच फ़ाइलें निष्पादन योग्य नहीं हैं (सीधे); अगर मैं '$ p ('रेक') चलाने की कोशिश करता हूं। बाहर(); ', यह' rake.exe' या 'rake.com' नामक बाइनरी निष्पादन योग्य की तलाश में जाता है, उन्हें ढूंढने में विफल रहता है, और त्रुटियां समाप्त होती हैं। यदि आप बैच फ़ाइलों को चलाने के लिए चाहते हैं तो आपको खोल ('cmd.exe') की आवश्यकता है। –

37

आप ताकि आप उन्हें पाइप मैन्युअल की जरूरत नहीं है spawn तर्क के माध्यम से stdin/बाहर/त्रुटि धाराओं के वारिस कर सकते हैं: खोल वाक्य रचना के लिए खोल

var spawn = require('child_process').spawn; 
spawn('ls', [], { stdio: 'inherit' }); 

उपयोग - बैश के लिए यह -c पैरामीटर है पढ़ने के लिए स्ट्रिंग से स्क्रिप्ट:

var spawn = require('child_process').spawn; 
var shellSyntaxCommand = 'ls -l | grep test | wc -c'; 
spawn('sh', ['-c', shellSyntaxCommand], { stdio: 'inherit' }); 

संक्षेप में:

var spawn = require('child_process').spawn; 
function shspawn(command) { 
    spawn('sh', ['-c', command], { stdio: 'inherit' }); 
} 

shspawn('ls -l | grep test | wc -c'); 
+0

यह मैन्युअल रूप से आउटपुट को पाइप करने से थोड़ा आसान है, लेकिन यह अभी भी खोल वाक्यविन्यास का समर्थन नहीं करता है। निश्चित रूप से, मैं [मैन्युअल रूप से आह्वान करने के लिए खोल खोल सकता हूं] (http://stackoverflow.com/a/9779382/87399), लेकिन फिर मेरा कोड क्रॉस-प्लेटफ़ॉर्म नहीं है। –

+0

कि '{stdio: 'legisl'} 'वास्तव में चाल है। धन्यवाद – kabirbaidhya

+0

यदि आप stdout और stderr प्राप्त करना चाहते हैं, तो 'पाइप' द्वारा 'विरासत' को प्रतिस्थापित करें – Guig

-1

वहाँ child_process मॉड्यूल के लिए node docs में एक उदाहरण है:

एक लंबी चलने वाली प्रक्रिया अलग करने और एक फाइल करने के लिए इसके उत्पादन पुनः निर्देशित का उदाहरण:

var fs = require('fs'), 
    spawn = require('child_process').spawn, 
    out = fs.openSync('./out.log', 'a'), 
    err = fs.openSync('./out.log', 'a'); 

var child = spawn('prg', [], { 
    detached: true, 
    stdio: [ 'ignore', out, err ] 
}); 

child.unref(); 
+2

यह प्रश्न का उत्तर कैसे देता है? आप दिखा रहे हैं कि आउटपुट को फ़ाइल में रीडायरेक्ट कैसे करें; प्रश्न बहुत विशेष रूप से * नहीं * रीडायरेक्ट आउटपुट के बारे में था। –

+0

मुझे लगता है कि आप सही हैं। मैं पहली बार सवाल को गलत तरीके से गलत तरीके से पढ़ता हूं। मैं क्षमाप्रार्थी हूं। – darelf

+1

इससे मेरी मदद की, धन्यवाद साथी। – Chance

3

आप spawn और उपयोग के द्वारा exec जगह ले सकता है बस के साथ खोल वाक्य रचना:

const {spawn} = require ('child_process'); 
const cmd = 'ls -l | grep test | wc -c'; 
const p = spawn (cmd, [], {shell: true}); 

p.stdout.on ('data', (data) => { 
    console.log (data.toString()); 
}); 

जादू सिर्फ {shell: true} है।