ホームページ > バックエンド開発 > Golang > Go で長時間実行されるコマンドから部分的な出力をストリーミングする方法は?

Go で長時間実行されるコマンドから部分的な出力をストリーミングする方法は?

Mary-Kate Olsen
リリース: 2024-12-24 00:18:15
オリジナル
843 人が閲覧しました

How to Stream Partial Output from a Long-Running Command in Go?

コマンド出力の進行状況のストリーミング

長時間実行されるコマンドが実行され、その出力を親プロセスとログ ファイルの両方に継続的にストリーミングする必要があるシナリオ、 cmd.StdoutPipe() メソッドを利用して出力をキャプチャできます。

cmd := exec.Command("sh", "-c", "some long runnig task")

stdout, _ := cmd.StdoutPipe()
cmd.Start()

scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
    m := scanner.Text()
    fmt.Println(m)
    log.Printf(m)
}

cmd.Wait()
ログイン後にコピー

ただし、このアプローチでは、部分的な結果をストリーミングするのではなく、単一の文字列として最終出力します。

出力が制限される理由

bufio.NewScanner() 関数は行に対して動作し、改行文字が出現すると完全な行を返します。実行中のコマンドで改行文字が生成されない場合、出力はすぐにはストリーミングされません。

考えられる回避策

この制限に対処するには、考慮すべきアプローチがいくつかあります。

  1. 単語または文字で読む:
    分割を設定するScanner.Split() を使用する関数を使用すると、単語または文字で入力をスキャンし、生成された出力をキャプチャできます。

    scanner := bufio.NewScanner(stdout)
    scanner.Split(bufio.ScanRunes)
    ログイン後にコピー
  2. マニュアル読み取り:
    バイトごとまたはルーンごとに読み取ることで、改行に依存せずに生成された出力をキャプチャできます

    oneByte := make([]byte, 1)
    for {
        _, err := stdout.Read(oneByte)
        if err != nil {
            break
        }
        fmt.Printf("%c", oneByte[0])
    }
    
    oneRune := make([]byte, utf8.UTFMax)
    for {
        count, err := stdout.Read(oneRune)
        if err != nil {
            break
        }
        fmt.Printf("%s", oneRune[:count])
    }
    ログイン後にコピー

考慮事項

子プロセスの標準出力およびエラー ストリームのバッファ サイズを管理することが重要です。デフォルトでは、これらのバッファーが読み取られない場合、子プロセスがハングする可能性があります。したがって、常に stdout ストリームと stderr ストリームの両方を読み取ることをお勧めします。

以上がGo で長時間実行されるコマンドから部分的な出力をストリーミングする方法は?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート