You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Pexpect通过SSH无法向Panduit PDU(Smartzone G5)下发命令的问题排查

Let's break down why your Pexpect script isn't triggering the port shutdown on your Panduit PDU, and fix it step by step.

1. Ditch the nested bash spawn (it's causing unnecessary complexity)

Right now you're spawning a bash shell first, then running SSH inside it. This adds extra layers that can mess with input routing and buffer handling. Instead, spawn the SSH command directly—this simplifies the session and eliminates bash-related interference:

child = pexpect.spawn(f'ssh -F /dev/null {server_user}@{server_ip} -oStrictHostKeyChecking=no')
child.logfile_read = sys.stdout.buffer

2. Wait for the PDU's response (don't just sleep and exit)

Your current script sends the shutdown command but immediately terminates before the PDU can fully process it. Even with sleep(3), the script might close the session before the command takes effect. Replace the sleep with explicit expect() calls to wait for the PDU's confirmation or return to the prompt:

# After sending the port shutdown command
child.sendline('dev outlet 1 1 off')
# Wait for either the SUCCESS message or the prompt (fallback)
try:
    index = child.expect(['SUCCESS', 'PANDUIT>'], timeout=10)
    if index == 0:
        print("\nPort 1 confirmed shut down!")
    else:
        print("\nCommand sent, returned to prompt.")
except pexpect.TIMEOUT:
    print("\nTimeout: PDU didn't respond in time.")
except pexpect.EOF:
    print("\nConnection closed unexpectedly.")

This ensures the script stays alive until the PDU acknowledges the command.

3. Fix your initial expect logic

That child.expect('') line in your original code doesn't serve any purpose. When spawning SSH directly, you can immediately wait for the password prompt:

child.expect(f"{server_user}@{server_ip}'s password:")
child.sendline(server_pass)
# Wait for the PDU's command prompt to confirm login
child.expect('PANDUIT>')

4. Add terminal emulation tweaks (some PDUs are picky)

Many network devices require a proper pseudo-terminal or specific terminal type to accept interactive commands. Add the -t flag to force terminal allocation and set a basic terminal type:

child = pexpect.spawn(f'ssh -F /dev/null -t {server_user}@{server_ip} -oStrictHostKeyChecking=no -oTerm=xterm')

Full revised script

Putting all these fixes together, here's the updated code:

import pexpect
import sys

server_ip = "192.168.0.1"
server_user = "admin"
server_pass = "password"

# Spawn SSH directly with terminal tweaks
child = pexpect.spawn(f'ssh -F /dev/null -t {server_user}@{server_ip} -oStrictHostKeyChecking=no -oTerm=xterm')
child.logfile_read = sys.stdout.buffer

# Handle login password prompt
child.expect(f"{server_user}@{server_ip}'s password:")
child.sendline(server_pass)

# Wait for the PDU command prompt to confirm successful login
child.expect('PANDUIT>')

# Send the port shutdown command
child.sendline('dev outlet 1 1 off')

# Wait for confirmation or prompt return
try:
    index = child.expect(['SUCCESS', 'PANDUIT>'], timeout=10)
    if index == 0:
        print("\nPort 1 successfully turned off!")
    else:
        print("\nCommand executed, returned to prompt.")
except pexpect.TIMEOUT:
    print("\nTimeout: PDU did not respond in time.")
except pexpect.EOF:
    print("\nConnection closed unexpectedly.")

Why this works better:

  • Direct SSH spawn eliminates bash buffer routing issues
  • Explicit response waiting ensures the command is fully processed
  • Terminal settings fix compatibility with picky network devices
  • Error handling for timeouts/EOF makes debugging easier

If you still can't capture the SUCCESS message, double-check if the PDU outputs it with trailing whitespace or special characters—you might need to adjust the expect pattern to something like r'SUCCESS\r\n' to match exactly.

内容的提问来源于stack exchange,提问作者David O'Hara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 15:17:40