英文:
continuously reading from exec.Cmd output
问题
大家好,我正在尝试根据命令输出选择新的行,但我总是以同步方式完成(必须等待脚本完成)。我尝试使用fsnotify,但它只适用于常规文件,你有任何想法如何实现吗?
package main
import (
"fmt"
"os/exec"
"bytes"
"os"
)
func main() {
cmd := exec.Command("scripts/long_script")
output := new(bytes.Buffer)
cmd.Stdout = output
cmd.Stderr = output
if err := cmd.Start(); err != nil{ // 在启动后,程序继续执行,脚本在后台执行
fmt.Printf("Failed to start " + err.Error())
os.Exit(1)
}
fmt.Printf(" Before WAIT %s \n", output.String()) // 脚本正在写入,但无法从输出中读取
cmd.Wait()
fmt.Printf(" After Wait %s \n", output.String()) // 如果我们等待执行完成,就可以读取所有输出
}
希望对你有帮助!
英文:
Guys I am trying pick new lines as they come from command output, but always I end up doing it synchronous way (I have to wait until script is finished). I tired to use fsnotify but it is working only with regular files, do you have any idea how it can be done ?
package main
import (
"fmt"
"os/exec"
"bytes"
"os"
)
func main() {
cmd := exec.Command("scripts/long_script")
output := new(bytes.Buffer)
cmd.Stdout = output
cmd.Stderr = output
if err := cmd.Start(); err != nil{ // after Start program is continued and script is executing in background
fmt.Printf("Failed to start " + err.Error())
os.Exit(1)
}
fmt.Printf(" Before WAIT %s \n", output.String()) // script is writing but nothing can be read from output
cmd.Wait()
fmt.Printf(" After Wait %s \n", output.String()) // if we wait to finish execution, we can read all output
}
答案1
得分: 6
你应该使用os.StdoutPipe()。
func main() {
for i := 10; i < 20; i++ {
go printName(`我的名字是Bob,我今年` + strconv.Itoa(i) + `岁`)
// 添加延迟以便看到逐步输出
time.Sleep(60 * time.Millisecond)
}
// 添加延迟以便让程序完成
// 请使用通道或等待组
time.Sleep(100 * time.Millisecond)
}
func printName(jString string) {
cmd := exec.Command("echo", "-n", jString)
cmdReader, err := cmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}
scanner := bufio.NewScanner(cmdReader)
go func() {
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}()
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
if err := cmd.Wait(); err != nil {
log.Fatal(err)
}
}
帮助我解决问题的资源:
nathanleclaire.com
blog.kowalczyk.info
英文:
You should use os.StdoutPipe()
func main() {
for i := 10; i < 20; i++ {
go printName(`My name is Bob, I am ` + strconv.Itoa(i) + ` years old`)
// Adding delay so as to see incremental output
time.Sleep(60 * time.Millisecond)
}
// Adding delay so as to let program complete
// Please use channels or wait groups
time.Sleep(100 * time.Millisecond)
}
func printName(jString string) {
cmd := exec.Command("echo", "-n", jString)
cmdReader, err := cmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}
scanner := bufio.NewScanner(cmdReader)
go func() {
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}()
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
if err := cmd.Wait(); err != nil {
log.Fatal(err)
}
}
sources that helped me:
nathanleclaire.com
blog.kowalczyk.info
答案2
得分: 5
最终我使用[]bytes
成功完成了它。
stdout, err := cmd.StdoutPipe()
buff := make([]byte, 10)
var n int
for err == nil {
n, err = stdout.Read(buff)
if n > 0 {
fmt.Printf("已读取 %d 个字符 %s", n, string(buff[:n]))
}
}
cmd.Wait()
if cmd.ProcessState.Success() { // 在 Wait 后设置 ProcessState
fmt.Println("脚本执行成功")
} else {
fmt.Println("脚本执行失败")
}
英文:
eventually I managed to do it with []bytes
stdout, err := cmd.StdoutPipe()
buff := make([]byte,10)
var n int
for err == nil {
n,err = stdout.Read(buff)
if n > 0{
fmt.Printf("taken %d chars %s",n,string(buff[:n]))
}
}
cmd.Wait()
if cmd.ProcessState.Success() {. // ProcessState is set after Wait
fmt.Println("Script success")
} else {
fmt.Println("Script failed")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论