Go এ শিশু প্রক্রিয়াটির stdout পাইপ পুনর্নির্দেশ করুন


105

আমি গো তে একটি প্রোগ্রাম লিখছি যা প্রোগ্রামের মতো সার্ভার চালায় (এছাড়াও যান)। এখন আমি আমার টার্মিনাল উইন্ডোতে শিশু প্রোগ্রামের স্ট্যান্ডআউট পেতে চাই যেখানে আমি প্যারেন্ট প্রোগ্রামটি শুরু করেছি। এটি করার একটি উপায় হ'ল cmd.Output()ফাংশনটি সহ, তবে প্রক্রিয়াটি শেষ হয়ে গেলেই এটি স্টাডাউট প্রিন্ট করে। (এটি একটি সমস্যা কারণ এই সার্ভারের মতো প্রোগ্রামটি দীর্ঘ সময় ধরে চলে এবং আমি লগ আউটপুটটি পড়তে চাই)

ভেরিয়েবলটি outহ'ল type 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
আপনার আমদানির বিবৃতিটির "এক্সিকিউটিভ" লাইনটি "ওএস / এক্সিকিউট" হওয়া উচিত।
অশুচি স্পাইরেট

তথ্যের জন্য ধন্যবাদ, প্রকৃতপক্ষে এটি কেবল নির্বাহী পূর্ব 1 ছিল, এখন এটি ওএসে। এটি go1
এমবার্ট

1
আমি মনে করি না যে আপনাকে আসলে io.Copyগো রুটিনের মধ্যে কল করতে হবে
রোমানজো

আমি আপনাকে কল করতে cmd.Wait()বা for{}লুপের প্রয়োজন মনে করি না ... এগুলি এখানে কেন?
weberc2

@ ওয়েবারসি 2 এই উত্তরটি বাদ দেওয়ার জন্য নীচে দেখুন। আপনি কেবল একবার প্রোগ্রাম চালাতে চাইলে ফর লুপটির প্রয়োজন নেই। তবে আপনি যদি সেমিডি.ওয়েট () না কল করেন তবে আপনার মূল প্রোগ্রামটি আপনার ডাকা প্রোগ্রাম শেষ হওয়ার আগেই শেষ হয়ে যেতে পারে এবং আপনি যে আউটপুটটি চান তা পাবেন না
এমবার্ট

উত্তর:


207

এখন আমি আমার টার্মিনাল উইন্ডোতে শিশু প্রোগ্রামের স্ট্যান্ডআউট পেতে চাই যেখানে আমি প্যারেন্ট প্রোগ্রামটি শুরু করেছি।

পাইপ বা জোরোটাইনগুলির সাথে জগাখিচির দরকার নেই, এটি সহজ।

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

4
এছাড়াও, আপনি যদি ইনপুট শোনার জন্য কমান্ডটি চান তবে আপনি কেবল cmd.Stdin = os.Stdinএটি তৈরি করতে পারেন যেন আপনি শেল থেকে আক্ষরিক অর্পণটি সম্পাদন করেছিলেন exec
নিউক্লিওন

4
যারা logস্টডআউটের পরিবর্তে পুনঃনির্দেশের দিকে তাকিয়ে আছেন তাদের জন্য এখানে
রিক স্মিথ

18

আমি বিশ্বাস করি যে যদি আপনি আমদানি ioএবং osএবং এই প্রতিস্থাপন করুন:

//fmt.Println(out)

এর সাথে:

go io.Copy(os.Stdout, out)

(এর জন্যio.Copy এবং এর জন্যos.Stdout ডকুমেন্টেশন দেখুন ), এটি আপনার যা ইচ্ছা তা করবে। (অস্বীকৃতি: পরীক্ষিত নয়))

যাইহোক, আপনি সম্ভবত স্ট্যান্ডার্ড-আউটপুট হিসাবে একই পদ্ধতির ব্যবহার করে স্ট্যান্ডার্ড-ত্রুটিও ক্যাপচার করতে চান, তবে cmd.StderrPipeএবং সাথে os.Stderr


2
@ অ্যাম্বার্ট: আমি অন্যান্য যথেষ্ট ভাষা ব্যবহার করেছি এবং গো সম্পর্কে যথেষ্ট পরিমাণে পড়েছি, কী কী বৈশিষ্ট্যটি সম্ভবত এটি করতে পারে তা আবিষ্কার করার জন্য এবং প্রায় কোনও রূপে; তারপরে আমার কুঁচটি সঠিক ছিল কিনা তা নিশ্চিত করার জন্য এবং প্রয়োজনীয় বিশদটি সন্ধান করার জন্য আমাকে কেবল প্রাসঙ্গিক প্যাকেজ-ডক্সগুলি (গুগলিংয়ের দ্বারা পাওয়া) অনুসন্ধান করতে হয়েছিল। সবচেয়ে শক্ত অংশগুলি ছিল (১) স্ট্যান্ডার্ড-আউটপুট কী বলা হয় এটি সন্ধান করা ( os.Stdout) এবং (২) এই দৃ confir়তার সত্যতা নিশ্চিত করে যে আপনি যদি একেবারেই কল না cmd.StdoutPipe()করেন তবে স্ট্যান্ডার্ড-আউটপুটটি /dev/nullপ্যারেন্ট-প্রক্রিয়াটির স্ট্যান্ডার্ড-আউটপুটটির পরিবর্তে চলে যায় ।
রুখ

15

যাদের লুপে এটির প্রয়োজন নেই তাদের জন্য, তবে 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")
}

মাইনর ফাই: (স্পষ্টতই) আপনি যদি "এখানে অন্য জিনিসগুলি" গোরআটাইনগুলির চেয়ে দ্রুত সম্পন্ন করেন তবে আপনি গোরটাইনগুলি শুরু হতে পারে ফলাফলগুলি মিস করতে পারেন। মূল () থেকে বেরিয়ে আসার ফলে গোরোটাইনগুলিও শেষ হয়ে যাবে। সুতরাং আপনি যদি সিএমডি শেষ না করে অপেক্ষা করেন তবে আপনি সম্ভবত টার্মিনালে প্রতিধ্বনির প্রকৃতপক্ষে শেষ করতে পারেন না।
galaktor
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.