如何捕获 stdout 输出并显示进度
How to capture stdout output but also show progress
我有一个名为 print()
的函数,它每 2 秒打印一次数字,这个函数在 goroutine 中运行。
我需要将它的标准输出打印传递给一个变量并打印它,但不是一次,直到它完成。
我需要一个无限循环的扫描仪,扫描标准输出并打印它,一旦功能完成,扫描仪也会完成。
我尝试使用 但它没有打印任何内容。
这是我尝试做的:
package main
import (
"bufio"
"fmt"
"os"
"sync"
"time"
)
func print() {
for i := 0; i < 50; i++ {
time.Sleep(2 * time.Second)
fmt.Printf("hello number: %d\n", i)
}
}
func main() {
old := os.Stdout // keep backup of the real stdout
defer func() { os.Stdout = old }()
r, w, _ := os.Pipe()
os.Stdout = w
go print()
var wg sync.WaitGroup
c := make(chan struct{})
wg.Add(1)
defer wg.Done()
for {
<-c
scanner := bufio.NewScanner(r)
for scanner.Scan() {
m := scanner.Text()
fmt.Println("output: " + m)
}
}
c <- struct{}{}
wg.Wait()
fmt.Println("DONE")
}
我也尝试过使用 io.Copy
来读取缓冲区,但它也没有用:
package main
import (
"bytes"
"fmt"
"io"
"os"
"time"
)
func print() {
for i := 0; i < 50; i++ {
time.Sleep(2 * time.Second)
fmt.Printf("hello number: %d\n", i)
}
}
// https://blog.kowalczyk.info/article/wOYk/advanced-command-execution-in-go-with-osexec.html
func main() {
old := os.Stdout // keep backup of the real stdout
defer func() { os.Stdout = old }()
r, w, _ := os.Pipe()
os.Stdout = w
go print()
fmt.Println("DONE 1")
outC := make(chan string)
for {
var buf bytes.Buffer
io.Copy(&buf, r)
outC <- buf.String()
out := <-outC
fmt.Println("output: " + out)
}
// back to normal state
w.Close()
fmt.Println("DONE")
}
可以 运行 print()
作为“黑盒”并捕获其输出,尽管这有点棘手并且不适用于 Go Playground。
package main
import (
"bufio"
"fmt"
"os"
"runtime"
"time"
)
func print() {
for i := 0; i < 50; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Printf("hello number: %d\n", i)
}
}
func main() {
var ttyName string
if runtime.GOOS == "windows" {
fmt.Println("*** Using `con`")
ttyName = "con"
} else {
fmt.Println("*** Using `/dev/tty`")
ttyName = "/dev/tty"
}
f, err := os.OpenFile(ttyName, os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
defer f.Close()
r, w, _ := os.Pipe()
oldStdout := os.Stdout
os.Stdout = w
defer func() {
os.Stdout = oldStdout
fmt.Println("*** DONE")
}()
fmt.Fprintln(f, "*** Stdout redirected")
go func(){
print()
w.Close()
r.Close()
}()
c := make(chan struct{})
go func(){c <- struct{}{}}()
defer close(c)
<-c
scanner := bufio.NewScanner(r)
for scanner.Scan() {
m := scanner.Text()
fmt.Fprintln(f, "output: " + m)
}
}
我有一个名为 print()
的函数,它每 2 秒打印一次数字,这个函数在 goroutine 中运行。
我需要将它的标准输出打印传递给一个变量并打印它,但不是一次,直到它完成。
我需要一个无限循环的扫描仪,扫描标准输出并打印它,一旦功能完成,扫描仪也会完成。
我尝试使用
这是我尝试做的:
package main
import (
"bufio"
"fmt"
"os"
"sync"
"time"
)
func print() {
for i := 0; i < 50; i++ {
time.Sleep(2 * time.Second)
fmt.Printf("hello number: %d\n", i)
}
}
func main() {
old := os.Stdout // keep backup of the real stdout
defer func() { os.Stdout = old }()
r, w, _ := os.Pipe()
os.Stdout = w
go print()
var wg sync.WaitGroup
c := make(chan struct{})
wg.Add(1)
defer wg.Done()
for {
<-c
scanner := bufio.NewScanner(r)
for scanner.Scan() {
m := scanner.Text()
fmt.Println("output: " + m)
}
}
c <- struct{}{}
wg.Wait()
fmt.Println("DONE")
}
我也尝试过使用 io.Copy
来读取缓冲区,但它也没有用:
package main
import (
"bytes"
"fmt"
"io"
"os"
"time"
)
func print() {
for i := 0; i < 50; i++ {
time.Sleep(2 * time.Second)
fmt.Printf("hello number: %d\n", i)
}
}
// https://blog.kowalczyk.info/article/wOYk/advanced-command-execution-in-go-with-osexec.html
func main() {
old := os.Stdout // keep backup of the real stdout
defer func() { os.Stdout = old }()
r, w, _ := os.Pipe()
os.Stdout = w
go print()
fmt.Println("DONE 1")
outC := make(chan string)
for {
var buf bytes.Buffer
io.Copy(&buf, r)
outC <- buf.String()
out := <-outC
fmt.Println("output: " + out)
}
// back to normal state
w.Close()
fmt.Println("DONE")
}
可以 运行 print()
作为“黑盒”并捕获其输出,尽管这有点棘手并且不适用于 Go Playground。
package main
import (
"bufio"
"fmt"
"os"
"runtime"
"time"
)
func print() {
for i := 0; i < 50; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Printf("hello number: %d\n", i)
}
}
func main() {
var ttyName string
if runtime.GOOS == "windows" {
fmt.Println("*** Using `con`")
ttyName = "con"
} else {
fmt.Println("*** Using `/dev/tty`")
ttyName = "/dev/tty"
}
f, err := os.OpenFile(ttyName, os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
defer f.Close()
r, w, _ := os.Pipe()
oldStdout := os.Stdout
os.Stdout = w
defer func() {
os.Stdout = oldStdout
fmt.Println("*** DONE")
}()
fmt.Fprintln(f, "*** Stdout redirected")
go func(){
print()
w.Close()
r.Close()
}()
c := make(chan struct{})
go func(){c <- struct{}{}}()
defer close(c)
<-c
scanner := bufio.NewScanner(r)
for scanner.Scan() {
m := scanner.Text()
fmt.Fprintln(f, "output: " + m)
}
}