गो

2012-01-16 15 views
84

में बाल प्रक्रिया के स्टडआउट पाइप को रीडायरेक्ट करें मैं गो में एक प्रोग्राम लिख रहा हूं जो प्रोग्राम जैसे सर्वर (गो गो) निष्पादित करता है। अब मैं अपने टर्मिनल विंडो में बाल कार्यक्रम का स्टडआउट रखना चाहता हूं जहां मैंने मूल कार्यक्रम शुरू किया था। ऐसा करने का एक तरीका cmd.Output() फ़ंक्शन के साथ है, लेकिन यह प्रक्रिया समाप्त हो जाने के बाद ही stdout प्रिंट करता है। (यह एक समस्या है क्योंकि यह सर्वर-जैसे प्रोग्राम लंबे समय तक चलता है और मैं लॉग आउटपुट पढ़ना चाहता हूं)गो

परिवर्तनीय outtype io.ReadCloser का है और मुझे नहीं पता कि मुझे अपने कार्य को प्राप्त करने के लिए इसके साथ क्या करना चाहिए , और मुझे इस विषय पर वेब पर कुछ भी उपयोगी नहीं मिल रहा है। कोड को

func main() { 
    cmd := exec.Command("/path/to/my/child/program") 
    out, err := cmd.StdoutPipe() 
    if err != nil { 
     fmt.Println(err) 
    } 
    err = cmd.Start() 
    if err != nil { 
     fmt.Println(err) 
    } 
    //fmt.Println(out) 
    cmd.Wait() 
} 

स्पष्टीकरण: टिप्पणी हटाएं Println समारोह संकलित करने के लिए कोड प्राप्त करने के, मुझे पता है कि Println(out io.ReadCloser) एक सार्थक कार्य नहीं है।
(यह उत्पादन &{3 |0 <nil> 0} उत्पादन करता है) इन दो पंक्तियों को संकलित करने के लिए कोड प्राप्त करने की आवश्यकता है।

+1

आयात विवरण की आपकी "exec" पंक्ति "os/exec" होना चाहिए। – evilspacepirate

+0

जानकारी के लिए धन्यवाद, असल में यह केवल पहले ही go exec1 था, अब यह ओएस में है। इसे go1 – mbert

+1

के लिए अपडेट किया गया मुझे नहीं लगता कि आपको वास्तव में 'io.Copy' को जाने के लिए दिनचर्या – rmonjo

उत्तर

171

अब मैं stdout करना चाहते हैं मेरे टर्मिनल विंडो में बाल कार्यक्रम का जहां मैंने मूल कार्यक्रम शुरू किया था।

पाइप या गोरोटाइन के साथ गड़बड़ करने की कोई आवश्यकता नहीं है, यह एक आसान है।

func main() { 
    // Replace `ls` (and its arguments) with something more interesting 
    cmd := exec.Command("ls", "-l") 
    cmd.Stdout = os.Stdout 
    cmd.Stderr = os.Stderr 
    cmd.Run() 
} 
+40

+1: मेरी इच्छा है कि यह उदाहरण दस्तावेज़ों में – tidwall

+3

हो, इसके अतिरिक्त, यदि आप इनपुट के लिए कमांड सुनना चाहते हैं तो आप बस 'cmd.Stdin = os.Stdin' सेट कर सकते हैं जिससे आप इसे सचमुच उस आदेश को निष्पादित कर सकें खोल। – Nucleon

+1

आपके महान उत्तर के कारण यहां बहुत समय और संभावित दुःख बचा है। धन्यवाद! – alphazero

16

मुझे विश्वास है कि अगर आप io और os आयात और इस बदलें:

//fmt.Println(out) 
इस के साथ

:

go io.Copy(os.Stdout, out) 

(प्रलेखन for io.Copy और for os.Stdout देखें), यह तुम क्या चाहते हो जाएगा। (अस्वीकरण: परीक्षण नहीं किया गया।)

वैसे, आप मानक-आउटपुट के लिए समान दृष्टिकोण का उपयोग करके मानक-त्रुटि को भी कैप्चर करना चाहते हैं, लेकिन cmd.StderrPipe और os.Stderr के साथ।

+1

धन्यवाद, मुझे एहसास नहीं हुआ कि यह इतना आसान हो सकता है :) - जाना बहुत अच्छा है (उस समस्या पर C++ लेख पढ़ें ...) – mbert

+0

@mbert: आपका स्वागत है! शर्मनाक रूप से, मुझे यह मानना ​​है कि मैंने वास्तव में कभी भी गो का उपयोग नहीं किया है, लेकिन हाँ, यह बहुत बढ़िया लगता है। :-) – ruakh

+0

आप इसके बारे में क्यों जानते हैं? आपको वास्तव में कोशिश करनी चाहिए! – mbert

11

जो लोग एक पाश में इस की जरूरत नहीं है, लेकिन cmd.Wait() अवरुद्ध अन्य बयान बिना आदेश उत्पादन टर्मिनल में गूंज चाहते हैं के लिए:

package main 

import (
    "fmt" 
    "io" 
    "log" 
    "os" 
    "os/exec" 
) 

func checkError(err error) { 
    if err != nil { 
     log.Fatalf("Error: %s", err) 
    } 
} 

func main() { 
    // Replace `ls` (and its arguments) with something more interesting 
    cmd := exec.Command("ls", "-l") 

    // Create stdout, stderr streams of type io.Reader 
    stdout, err := cmd.StdoutPipe() 
    checkError(err) 
    stderr, err := cmd.StderrPipe() 
    checkError(err) 

    // Start command 
    err = cmd.Start() 
    checkError(err) 

    // Don't let main() exit before our command has finished running 
    defer cmd.Wait() // Doesn't block 

    // Non-blockingly echo command output to terminal 
    go io.Copy(os.Stdout, stdout) 
    go io.Copy(os.Stderr, stderr) 

    // I love Go's trivial concurrency :-D 
    fmt.Printf("Do other stuff here! No need to wait.\n\n") 
} 
+0

मामूली fyi: (जाहिर है) आप goroutines के परिणाम याद कर सकते हैं अगर आपका "यहाँ अन्य सामान" goroutines से तेजी से पूरा करता है। मुख्य() बाहर निकलने से गोरोटाइन भी समाप्त हो जाएंगे। इसलिए यदि आप cmd को समाप्त करने की प्रतीक्षा नहीं करते हैं तो आप टर्मिनल में गूंजने के लिए वास्तव में आउटपुट को समाप्त नहीं कर सकते हैं। – galaktor

+0

यूप, अच्छा बिंदु। – elimisteve