要实现交互式Bash命令的自动化输入,可以使用os/exec包配合io.Pipe和goroutine来处理输入输出流。下面是一个示例代码,演示如何根据命令输出自动响应输入:
package main
import (
"bufio"
"fmt"
"io"
"log"
"os"
"os/exec"
"strings"
"time"
)
func main() {
// 创建命令(示例:交互式Python解释器)
cmd := exec.Command("python3", "-u", "-i")
// 获取标准输入输出管道
stdin, err := cmd.StdinPipe()
if err != nil {
log.Fatal(err)
}
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}
stderr, err := cmd.StderrPipe()
if err != nil {
log.Fatal(err)
}
// 启动命令
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
// 使用goroutine处理标准输出
go func() {
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
line := scanner.Text()
fmt.Printf("输出: %s\n", line)
// 根据输出内容自动响应
if strings.Contains(line, ">>>") {
// 检测到Python提示符,自动输入命令
stdin.Write([]byte("print('自动响应')\n"))
}
}
}()
// 使用goroutine处理标准错误
go func() {
scanner := bufio.NewScanner(stderr)
for scanner.Scan() {
fmt.Printf("错误: %s\n", scanner.Text())
}
}()
// 使用goroutine处理手动输入(如果需要)
go func() {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
input := scanner.Text()
stdin.Write([]byte(input + "\n"))
}
}()
// 等待命令结束
if err := cmd.Wait(); err != nil {
log.Fatal(err)
}
}
更复杂的示例,实现完整的交互逻辑:
package main
import (
"bufio"
"fmt"
"io"
"log"
"os/exec"
"strings"
)
type InteractiveCommand struct {
cmd *exec.Cmd
stdin io.WriteCloser
stdout io.ReadCloser
stderr io.ReadCloser
}
func NewInteractiveCommand(name string, args ...string) (*InteractiveCommand, error) {
cmd := exec.Command(name, args...)
stdin, err := cmd.StdinPipe()
if err != nil {
return nil, err
}
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
stderr, err := cmd.StderrPipe()
if err != nil {
return nil, err
}
return &InteractiveCommand{
cmd: cmd,
stdin: stdin,
stdout: stdout,
stderr: stderr,
}, nil
}
func (ic *InteractiveCommand) Start() error {
return ic.cmd.Start()
}
func (ic *InteractiveCommand) Run() error {
// 启动命令
if err := ic.Start(); err != nil {
return err
}
// 创建输出扫描器
stdoutScanner := bufio.NewScanner(ic.stdout)
stderrScanner := bufio.NewScanner(ic.stderr)
// 处理标准输出
go func() {
for stdoutScanner.Scan() {
output := stdoutScanner.Text()
fmt.Printf("命令输出: %s\n", output)
// 根据输出内容决定输入
ic.handleOutput(output)
}
}()
// 处理标准错误
go func() {
for stderrScanner.Scan() {
fmt.Printf("命令错误: %s\n", stderrScanner.Text())
}
}()
return ic.cmd.Wait()
}
func (ic *InteractiveCommand) handleOutput(output string) {
// 这里实现你的自动化逻辑
// 示例:如果输出包含特定字符串,则自动响应
switch {
case strings.Contains(output, "请输入用户名:"):
ic.SendInput("myusername\n")
case strings.Contains(output, "请输入密码:"):
ic.SendInput("mypassword\n")
case strings.Contains(output, "[Y/n]"):
ic.SendInput("Y\n")
case strings.Contains(output, "选择操作"):
ic.SendInput("1\n")
}
}
func (ic *InteractiveCommand) SendInput(input string) error {
_, err := ic.stdin.Write([]byte(input))
return err
}
func main() {
// 示例:自动化SSH连接
ic, err := NewInteractiveCommand("ssh", "user@hostname")
if err != nil {
log.Fatal(err)
}
// 可以添加初始命令
ic.SendInput("ls -la\n")
if err := ic.Run(); err != nil {
log.Fatal(err)
}
}
简单包装器示例,用于处理需要确认的命令:
package main
import (
"bufio"
"fmt"
"io"
"os/exec"
"strings"
)
func runInteractiveCommand(cmdStr string, responses map[string]string) error {
cmd := exec.Command("bash", "-c", cmdStr)
stdin, _ := cmd.StdinPipe()
stdout, _ := cmd.StdoutPipe()
cmd.Start()
// 读取输出并自动响应
reader := bufio.NewReader(stdout)
go func() {
for {
line, err := reader.ReadString('\n')
if err != nil {
break
}
fmt.Print(line)
// 检查是否需要自动响应
for prompt, response := range responses {
if strings.Contains(line, prompt) {
stdin.Write([]byte(response + "\n"))
break
}
}
}
}()
return cmd.Wait()
}
func main() {
// 定义命令和自动响应
responses := map[string]string{
"Are you sure": "yes",
"Continue": "y",
"Password": "secret123",
}
// 运行需要交互的命令
err := runInteractiveCommand("sudo apt-get update && sudo apt-get upgrade", responses)
if err != nil {
fmt.Printf("命令执行错误: %v\n", err)
}
}
这些示例展示了如何捕获命令输出、分析输出内容并自动发送响应。关键点包括:
- 使用
exec.Command创建命令
- 通过
StdinPipe、StdoutPipe、StderrPipe获取输入输出流
- 使用goroutine并发处理输入输出
- 根据输出内容通过
Write方法发送输入响应