gpt4 book ai didi

regex - Cisco Regex 的 Golang 转义问号字符

转载 作者:数据小太阳 更新时间:2023-10-29 03:22:37 24 4
gpt4 key购买 nike

因此,Cisco 的正则表达式允许使用问号字符。但要注意的是,您必须在输入问号之前使用 Ctrl-Shift-v 才能将其解释为问号而不是帮助命令... Link to Cisco regex guidelines

我有一个 Go 程序可以登录一组设备并在每台设备上运行一组命令。但是,当尝试使用包含问号的正则表达式时,Cisco 设备始终将问号解释为帮助命令。在 Go 中使用字符串文字并不能解决问题,也不能将命令作为 byte slice 段发送。

例如,如果我尝试发送命令 show boot | include (c|cat)[0-9]+[a-zA-Z]? Cisco CLI 返回

switch-1#show boot | include (c|cat)[0-9]+[a-zA-Z]?
LINE <cr>

switch-1#

而不是将问号解释为 [a-zA-Z] 组的 0 或 1 的正则表达式匹配。

但是,使用命令 ssh user@switch-1 'show boot | include (c|cat)[0-9]+[a-zA-Z]?' 按预期工作并正确解释正则表达式模式。

如何复制 ssh 命令的行为?有没有办法在每个问号之前发送 Ctrl-Shift-v 或转义每个问号字符?

我要求的代码:

package main

import (
"golang.org/x/crypto/ssh"
"net"
"fmt"
"os"
"bufio"
"time"
"golang.org/x/crypto/ssh/terminal"
"io"
"io/ioutil"
"sync"
"strings"
)

// ReadLines reads a file line-by-line and returns a slice of the lines.
func ReadLines(filename string) ([]string, error) {
f, err := os.Open(filename)
if err != nil {
return nil, fmt.Errorf("failed to open file: %v", err)
}
defer f.Close()

var lines []string
s := bufio.NewScanner(f)
for s.Scan() {
lines = append(lines, s.Text())
}
if err := s.Err(); err != nil {
return nil, err
}
return lines, nil
}

// Type Result represents the result of running the Configure method.
type Result struct {
Host string // Hostname of device
Output []byte // Remote shell's stdin and stderr output
Err error // Remote shell errors
}

// Configure logs into a device, starts a remote shell, runs the set of
// commands, and waits for the remote shell to return or timeout.
func Configure(host string, config *ssh.ClientConfig, cmds []string, results chan<- *Result, wg *sync.WaitGroup) {
defer wg.Done()

res := &Result{
Host: host,
Output: nil,
Err: nil,
}

// Create client connection
client, err := ssh.Dial("tcp", net.JoinHostPort(host, "22"), config)
if err != nil {
res.Err = fmt.Errorf("failed to dial: %v", err)
results <- res
return
}
defer client.Close()

// Create new session
session, err := client.NewSession()
if err != nil {
res.Err = fmt.Errorf("failed to create session: %v", err)
results <- res
return
}
defer session.Close()

// Set session IO
stdin, err := session.StdinPipe()
if err != nil {
res.Err = fmt.Errorf("failed to create pipe to stdin: %v", err)
results <- res
return
}
defer stdin.Close()

stdout, err := session.StdoutPipe()
if err != nil {
res.Err = fmt.Errorf("failed to create pipe to stdout: %v", err)
results <- res
return
}
stderr, err := session.StderrPipe()
if err != nil {
res.Err = fmt.Errorf("failed to create pipe to stderr: %v", err)
results <- res
return
}

// Start remote shell
if err := session.RequestPty("vt100", 0, 0, ssh.TerminalModes{
ssh.ECHO: 0,
ssh.TTY_OP_ISPEED: 14400,
ssh.TTY_OP_OSPEED: 14400,
}); err != nil {
res.Err = fmt.Errorf("failed to request pseudoterminal: %v", err)
results <- res
return
}
if err := session.Shell(); err != nil {
res.Err = fmt.Errorf("failed to start remote shell: %v", err)
results <- res
return
}

// Run commands
for _, cmd := range cmds {
if _, err := io.WriteString(stdin, cmd+"\n"); err != nil {
res.Err = fmt.Errorf("failed to run: %v", err)
results <- res
return
}
}

// Wait for remote commands to return or timeout
exit := make(chan error, 1)
go func(exit chan<- error) {
exit <- session.Wait()
}(exit)
timeout := time.After(1 * time.Minute)
select {
case <-exit:
output, err := ioutil.ReadAll(io.MultiReader(stdout, stderr))
if err != nil {
res.Err = fmt.Errorf("failed to read output: %v", err)
results <- res
return
}
res.Output = output
results <- res
return
case <-timeout:
res.Err = fmt.Errorf("session timed out")
results <- res
return
}
}

func main() {
hosts, err := ReadLines(os.Args[1])
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
cmds, err := ReadLines(os.Args[2])
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}

fmt.Fprint(os.Stderr, "Password: ")
secret, err := terminal.ReadPassword(int(os.Stdin.Fd()))
if err != nil {
fmt.Fprintf(os.Stderr, "failed to read password: %v\n", err)
os.Exit(1)
}
fmt.Fprintln(os.Stderr)

config := &ssh.ClientConfig{
User: "user",
Auth: []ssh.AuthMethod{ssh.Password(string(secret))},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Timeout: 30 * time.Second,
}
config.SetDefaults()
config.Ciphers = append(config.Ciphers, "aes128-cbc", "3des-cbc", "aes192-cbc", "aes256-cbc")

results := make(chan *Result, len(hosts))

var wg sync.WaitGroup
wg.Add(len(hosts))
for _, host := range hosts {
go Configure(host, config, cmds, results, &wg)
}
wg.Wait()
close(results)

for res := range results {
if res.Err != nil {
fmt.Fprintf(os.Stderr, "Error %s: %v\n", res.Host, res.Err)
continue
}
fmt.Printf("Host %s\n%s\n%s\n", res.Host, res.Output, strings.Repeat("-", 50))
}
}

最佳答案

尝试强制 IOS 终端服务器进入行模式(与字符模式相反)。发送这些 telnet 协商序列:

IAC DONT ECHO
IAC WONT ECHO
IAC DONT SUPPRESS-GO-AHEAD
IAC WONT SUPPRESS-GO-AHEAD

参见:https://www.rfc-editor.org/rfc/rfc858

关于regex - Cisco Regex 的 Golang 转义问号字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50975209/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com