2017-10-13 76 views
1

不知道如何解釋這一點,因爲我使用GO 中的QT綁定,所以我粘貼了該程序的迷你版本。 我試圖從run()func返回一個直播到QT窗口.. 我嘗試了很多方法...最後一個與頻道(不成功) 什麼是最好的方式來傳遞實時輸出到main()函數,所以我的QT槽可以更新窗口?試圖從shell命令返回實時輸出作爲從函數到主函數的字符串數據

包主要

import (
     "fmt" 
     //  "github.com/therecipe/qt/core" 
     "bufio" 
     "github.com/therecipe/qt/widgets" 
     "os" 
     "os/exec" 
) 

func run(input string) string { 

     stream := make(chan string) 

     fmt.Printf("You Clicked The Push Button %s\n", input) 

     cmdName := "/usr/bin/nikto" 
     cmdArgs := []string{"-host", input} 

     cmd := exec.Command(cmdName, cmdArgs...) 
     cmdReader, err := cmd.StdoutPipe() 
     if err != nil { 
       fmt.Fprintln(os.Stderr, "Error creating StdoutPipe for Cmd", err) 
       os.Exit(1) 
     } 

     scanner := bufio.NewScanner(cmdReader) 
     go func() { 
       for scanner.Scan() { 
         fmt.Printf("%s\n", scanner.Text()) 
         stream <- scanner.Text() 
         //stream = fmt.Sprintf("%s\n", scanner.Text()) 
       } 
     }() 

     err = cmd.Start() 
     if err != nil { 
       fmt.Fprintln(os.Stderr, "Error starting Cmd", err) 
       os.Exit(1) 
     } 

     err = cmd.Wait() 
     if err != nil { 
       fmt.Fprintln(os.Stderr, "Error waiting for Cmd", err) 
       os.Exit(1) 
     } 

     input = <-stream 
     return string(input) 
     //return go getOutput(scanner) 

} 

func main() { 
     // Create application 
     app := widgets.NewQApplication(len(os.Args), os.Args) 

     // Create main window 
     window := widgets.NewQMainWindow(nil, 0) 
     window.SetWindowTitle("nikto front end") 
     window.SetMinimumSize2(400, 400) 

     // Create layout 

     Layout := widgets.NewQVBoxLayout() 

     TopLayout := widgets.NewQHBoxLayout() 
     //topright := widgets.NewQHBoxLauout() 

     RLayout := widgets.NewQVBoxLayout() 
     LLayout := widgets.NewQVBoxLayout() 

     Layout.AddLayout(TopLayout, 0) 
     Layout.AddLayout(RLayout, 1) 
     Layout.AddLayout(LLayout, 0) 

     //Create main widget 
     mainWidget := widgets.NewQWidget(nil, 0) 
     mainWidget.SetLayout(Layout) 

     // Create left widget 
     LQWidget := widgets.NewQWidget(nil, 0) 
     LQWidget.SetLayout(LLayout) 

     // Create right widget 

     RQWidget := widgets.NewQWidget(nil, 0) 
     RQWidget.SetLayout(RLayout) 

     // Create label 
     urlLabel := widgets.NewQLabel(nil, 0) 
     urlLabel.SetText("Target: ") 
     TopLayout.AddWidget(urlLabel, 0, 0) 

     // Create a line edit 
     input := widgets.NewQLineEdit(nil) 
     input.SetPlaceholderText("Enter target like http://127.0.0.1") 
     TopLayout.AddWidget(input, 0, 0) 

     // Create checkboxes 
     checkBox1 := widgets.NewQCheckBox2("Default", nil) 
     //checkBox1.SetWindowTitle("Check Box") 
     LLayout.AddWidget(checkBox1, 0, 0) 

     checkBox2 := widgets.NewQCheckBox2("SSL mode", nil) 
     //checkBox2.SetWindowTitle("Check Box") 
     LLayout.AddWidget(checkBox2, 0, 0) 

     checkBox3 := widgets.NewQCheckBox2("no 404", nil) 
     //checkBox3.SetWindowTitle("Check Box") 
     LLayout.AddWidget(checkBox3, 0, 0) 

     output := widgets.NewQTextEdit(nil) 
     LLayout.AddWidget(output, 0, 0) 

     // Create a button and add it to the layout 
     button1 := widgets.NewQPushButton2("2. click me", nil) 
     Layout.AddWidget(button1, 0, 0) 

     button1.ConnectClicked(func(checked bool) { 
       output.Append(run(input.Text())) 
     }) 

     // Set main widget as the central widget of the window 
     window.SetCentralWidget(mainWidget) 

     // Show the window 
     window.Show() 

     // Execute app 
     app.Exec() 
} 

回答

2

run返回通道,然後讀取它main(和不讀來自渠道run):

package main 

import (
    "bufio" 
    "fmt" 
    "os/exec" 
) 

func main() { 
    // ... 

    button1.ConnectClicked(func(checked bool) { 
      stream := run(input.Text()) 
      go func() { 
        for line := range stream { 
          output.Append(line) 
        } 
      }() 
    }) 

    // ... 
} 

func run(host string) <-chan string { 

    var cmd *exec.Cmd 
    cmdReader, err := cmd.StdoutPipe() 
    if err != nil { 
      // ... 
    } 

    scanner := bufio.NewScanner(cmdReader) 
    stream := make(chan string) 

    go func() { 
      defer close(stream) 

      for scanner.Scan() { 
        fmt.Printf("%s\n", scanner.Text()) 
        stream <- scanner.Text() 
      } 
    }() 

    go func() { 
      if err := cmd.Run(); err != nil { 
        // ... 
      } 
    }() 

    return stream 
} 
+0

你是男人!工作就像一個魅力..我不得不評論你的cmd指針,並添加我的cmd,cmd:= exec.Command(cmdName,cmdArgs ...)和其他你沒有包括,現在它顯示..我愛GO頻道!這幫助我練習它。 – cfernandezlinux

1

你需要調用run是異步的(這需要渠道和夠程)?如果沒有,你可以簡單地使用bytes.Buffer捕獲命令輸出和返回(這是什麼會顯示我們目前的執行情況做):

func run(input string) string { 
    cmdName := "/usr/bin/nikto" 
    cmdArgs := []string{"-host", input} 

    cmd := exec.Command(cmdName, cmdArgs...) 
    var b bytes.Buffer 
    cmd.Stdout = &b 

    err := cmd.Run() 
    if err != nil { 
     log.Fatal(err) 
    } 

    return b.String() 
} 
+0

嘿!非常感謝。不是真的,我真的不介意如何去做。只要它有效。我測試了這一點,似乎並沒有按照我想要的方式工作,基本上shell命令有一個常量stdout,截至目前,我只會在完成時立即獲得所有輸出。我需要的是輸出顯示小部件,因爲它出來picure一個尾巴-f/var/log /消息只是這是一個命令,並最終完成運行,當然不是一個文件.. :)這樣就可以很容易地在shell與popen和類似系統調用,這裏的問題是與函數和小部件。 – cfernandezlinux

+0

我認爲使用qt來渲染此功能會更好,因爲它本質上是一種UI行爲。爲了從'run'得到這個行爲,你必須確保'output.Append'可以和字節流一起工作,我不認爲是這種情況。 – abhink

+0

嘿感謝您的幫助,彼得的另一個建議正是我所需要的......問題是QT去libs我認爲仍然缺少運行系統命令的QProcess我幾天後開了一個問題但沒有迴應,所以只是走了純粹的去路。 https://github.com/therecipe/qt/issues/474 – cfernandezlinux