Qt 尝试将shell命令的实时/实时输出作为字符串数据从函数返回到主函数
不知道如何解释,因为我在GO中使用QT绑定 所以我粘贴了一个迷你版的程序。 我正在尝试从run()函数返回到QT窗口的实时流。。 我尝试了很多方法。。。最后一个有通道(未成功) 将实时输出传递给main()函数以便我的QT插槽可以更新窗口的最佳方式是什么 包干管Qt 尝试将shell命令的实时/实时输出作为字符串数据从函数返回到主函数,qt,function,go,Qt,Function,Go,不知道如何解释,因为我在GO中使用QT绑定 所以我粘贴了一个迷你版的程序。 我正在尝试从run()函数返回到QT窗口的实时流。。 我尝试了很多方法。。。最后一个有通道(未成功) 将实时输出传递给main()函数以便我的QT插槽可以更新窗口的最佳方式是什么 包干管 import ( "fmt" // "github.com/therecipe/qt/core" "bufio" "github.com/therecipe/qt
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()
}
导入(
“fmt”
//“github.com/therecipe/qt/core”
“布菲奥”
“github.com/therecipe/qt/widgets”
“操作系统”
“os/exec”
)
func运行(输入字符串)字符串{
流:=生成(chan字符串)
fmt.Printf(“您单击了按钮%s\n”,输入)
cmdName:=“/usr/bin/nikto”
cmdArgs:=[]字符串{“-host”,输入}
cmd:=exec.Command(cmdName,cmdArgs…)
cmdReader,错误:=cmd.StdoutPipe()
如果错误!=零{
fmt.Fprintln(os.Stderr,“为Cmd创建StdoutPipe时出错”,err)
操作系统退出(1)
}
扫描程序:=bufio.NewScanner(cmdReader)
go func(){
对于scanner.Scan(){
fmt.Printf(“%s\n”,scanner.Text())
stream您是否需要对run
的调用是异步的(这需要通道和goroutine)?如果不需要,您可以简单地使用bytes.Buffer
来捕获命令输出和返回(这就是我们当前的实现所做的):
让运行
返回频道,然后在main
中读取它(不要在运行
中从频道读取):
主程序包
进口(
“布菲奥”
“fmt”
“os/exec”
)
func main(){
// ...
按钮1.连接已单击(功能(选中布尔){
流:=运行(input.Text())
go func(){
对于行:=范围流{
output.Append(行)
}
}()
})
// ...
}
func运行(主机字符串)嘿!非常感谢。其实我并不介意怎么做。只要它能工作。我已经测试过了,而且似乎没有按照我想要的方式工作,基本上shell命令有一个常量stdout,到目前为止,我只会在完成后一次获得所有输出。我需要的是在小部件上显示输出,因为它显示为picure a tail-f/var/只记录/消息这是一个命令,并最终完成运行,当然不是一个文件:)这样在shell上使用popen和类似的系统调用很容易,这里的问题是函数和小部件。我认为最好使用qt来呈现此功能,因为它本质上是一种UI行为。要从run
,你必须确保输出。Append
可以处理字节流,我不这么认为。嘿,谢谢你的帮助,Peter的另一个建议正是我所需要的。问题是我认为QT go libs仍然缺少QProcess,这是运行系统命令的地方。我几天前打开了一个问题o但没有回应,所以只走了纯围棋路线。你这个人!就像一个魔咒一样工作。我必须注释你的cmd指针,并添加回我的cmd,cmd:=exec.Command(cmdName,cmdArgs…)和你没有包含的其他内容,现在它显示了。我喜欢围棋频道!这有助于我练习。
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()
}
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
}