执行ssh user@ip 'command'时遇can't get tty settings错误求助
I’ve run into this exact issue with Cisco IOS-based devices before—their CLI is picky about having a proper terminal environment to execute commands, which is why you see this error when running commands directly via ssh user@ip 'command' but not when logging in interactively. Here’s how to fix it:
1. Quick Fix for Manual/One-off Commands
When running commands from your shell, force SSH to allocate a pseudo-terminal with the -t flag. This tricks the Cisco AP into thinking you’re logging in interactively:
ssh -t user@ap_ip 'your_command_here'
For example, to pull a snippet of the running config focused on interfaces:
ssh -t admin@192.168.1.1 'show running-config | include interface'
The -t flag ensures the AP gets the tty settings it expects, eliminating the "can't get tty settings" error entirely.
2. Fixing Your Golang Automation
The Go x/crypto/ssh library doesn’t request a pseudo-terminal by default, which is why your automation is hitting the same roadblock. You need to explicitly request a PTY in your session setup. Here’s a working example:
package main import ( "fmt" "golang.org/x/crypto/ssh" "os" ) func main() { // Configure SSH client credentials config := &ssh.ClientConfig{ User: "admin", Auth: []ssh.AuthMethod{ ssh.Password("your_secure_password"), }, // Note: In production, replace this with proper host key verification! HostKeyCallback: ssh.InsecureIgnoreHostKey(), } // Connect to the AP client, err := ssh.Dial("tcp", "192.168.1.1:22", config) if err != nil { fmt.Printf("Failed to connect to AP: %v\n", err) os.Exit(1) } defer client.Close() // Create a new SSH session session, err := client.NewSession() if err != nil { fmt.Printf("Failed to create session: %v\n", err) os.Exit(1) } defer session.Close() // Critical step: Request a pseudo-terminal (PTY) err = session.RequestPty("vt100", 80, 40, ssh.TerminalModes{}) if err != nil { fmt.Printf("Failed to request PTY: %v\n", err) os.Exit(1) } // Execute your command and capture output output, err := session.CombinedOutput("show version") if err != nil { fmt.Printf("Command execution failed: %v\n", err) os.Exit(1) } // Print the result fmt.Println("Command Output:\n", string(output)) }
The RequestPty method mimics the interactive terminal environment the Cisco AP expects, resolving the tty-related errors. Adjust the terminal type (vt100) and dimensions (80x40) if needed—most Cisco devices work perfectly with these defaults.
Why This Happens
Cisco 2800 APs (and many IOS-based devices) rely on terminal settings to handle command execution properly. When you run commands directly via ssh user@ip 'command', SSH doesn’t allocate a pseudo-terminal by default. The AP’s CLI detects this missing tty environment and throws the "can't get tty settings/can't set orig mode" error. Interactive logins automatically get a tty assigned, which is why they work without issues.
内容的提问来源于stack exchange,提问作者mwalto7

