IT序号网

python-2.7之如何设置 pexpect ssh session 的列宽

third_qq_4accc0ab0fa5b582 2025年12月25日 编程语言 47 0

我正在编写一个简单的 python 脚本来通过 SSH 连接到 SAN,运行一组命令。最终,每个命令将与时间戳一起记录到单独的日志中,然后退出。这是因为我们连接的设备不支持证书 ssh 连接,并且当前固件版本不具备良好的日志记录功能。

我似乎遇到的问题是创建的 SSH session 似乎限制为 78 个字符宽。每个命令生成的结果明显更宽 - 155 个字符。这引起了很多奇怪的事情。

首先,当前状态下的结果明显更难以解析。其次,由于缓冲区明显较小,因此最终的音量命令将无法正确执行,因为 pexpect 启动的 SSH session 实际上会提示“按任意键继续”。

如何更改 pexpect session 的列宽?

这是当前的代码(它可以工作,但不完整):

#!/usr/bin/python 
 
import pexpect 
import os 
 
PASS='mypassword' 
HOST='1.2.3.4' 
LOGIN_COMMAND='ssh manage@'+HOST 
CTL_COMMAND='show controller-statistics' 
VDISK_COMMAND='show vdisk-statistics' 
VOL_COMMAND='show volume-statistics' 
 
VDISK_LOG='vdisk.log' 
VOLUME_LOG='volume.log' 
CONTROLLER_LOG='volume.log' 
 
DATE=os.system('date +%Y%m%d%H%M%S') 
 
child=pexpect.spawn(LOGIN_COMMAND) 
child.setecho(True) 
child.logfile = open('FetchSan.log','w+') 
child.expect('Password: ') 
child.sendline(PASS) 
child.expect('# ') 
child.sendline(CTL_COMMAND) 
print child.before 
child.expect('# ') 
child.sendline(VDISK_COMMAND) 
print child.before 
child.expect('# ') 
print "Sending "+VOL_COMMAND 
child.sendline(VOL_COMMAND) 
print child.before 
child.expect('# ') 
child.sendline('exit') 
child.expect(pexpect.EOF) 
print child.before 

预期输出:

# show controller-statistics 
Durable ID     CPU Load   Power On Time (Secs)   Bytes per second   IOPS             Number of Reads  Number of Writes Data Read        Data Written      
--------------------------------------------------------------------------------------------------------------------------------------------------------- 
controller_A   0          45963169               1573.3KB           67               386769785        514179976        6687.8GB         5750.6GB 
controller_B   20         45963088               4627.4KB           421              3208370173       587661282        63.9TB           5211.2GB 
--------------------------------------------------------------------------------------------------------------------------------------------------------- 
Success: Command completed successfully. 
 
# show vdisk-statistics      
Name   Serial Number                    Bytes per second   IOPS             Number of Reads  Number of Writes Data Read        Data Written      
------------------------------------------------------------------------------------------------------------------------------------------------ 
CRS    00c0ff13349e000006d5c44f00000000 0B                 0                45861            26756            3233.0MB         106.2MB 
DATA   00c0ff1311f300006dd7c44f00000000 2282.4KB           164              23229435         76509765         5506.7GB         1605.3GB 
DATA1  00c0ff1311f3000087d8c44f00000000 2286.5KB           167              23490851         78314374         5519.0GB         1603.8GB 
DATA2  00c0ff1311f30000c2f8ce5700000000 0B                 0                26               4                1446.9KB         65.5KB 
FRA    00c0ff13349e000001d8c44f00000000 654.8KB            5                3049980          15317236         1187.3GB         1942.1GB 
FRA1   00c0ff13349e000007d9c44f00000000 778.7KB            6                3016569          15234734         1179.3GB         1940.4GB 
------------------------------------------------------------------------------------------------------------------------------------------------ 
Success: Command completed successfully. 
 
# show volume-statistics     
Name        Serial Number                    Bytes per second   IOPS             Number of Reads  Number of Writes Data Read        Data Written      
----------------------------------------------------------------------------------------------------------------------------------------------------- 
CRS_v001    00c0ff13349e0000fdd6c44f01000000 14.8KB             5                239611146        107147564        1321.1GB         110.5GB           
DATA1_v001  00c0ff1311f30000d0d8c44f01000000 2402.8KB           218              1701488316       336678620        33.9TB           3184.6GB          
DATA2_v001  00c0ff1311f3000040f9ce5701000000 0B                 0                921              15               2273.7KB         2114.0KB          
DATA_v001   00c0ff1311f30000bdd7c44f01000000 2303.4KB           209              1506883611       250984824        30.0TB           2026.6GB          
FRA1_v001   00c0ff13349e00001ed9c44f01000000 709.1KB            28               25123082         161710495        1891.0GB         2230.0GB          
FRA_v001    00c0ff13349e00001fd8c44f01000000 793.0KB            34               122052720        245322281        3475.7GB         3410.0GB          
----------------------------------------------------------------------------------------------------------------------------------------------------- 
Success: Command completed successfully. 

打印到终端的输出(如上所述,第三个命令在当前状态下不会执行):

show controller-statistics 
Durable ID     CPU Load   Power On Time (Secs)   Bytes per second    
  IOPS             Number of Reads  Number of Writes Data Read         
  Data Written      
---------------------------------------------------------------------- 
controller_A   3          45962495               3803.1KB            
  73               386765821        514137947        6687.8GB          
  5748.9GB 
controller_B   20         45962413               5000.7KB            
  415              3208317860       587434274        63.9TB            
  5208.8GB 
---------------------------------------------------------------------- 
Success: Command completed successfully. 
 
 
Sending show volume-statistics 
show vdisk-statistics 
Name   Serial Number                    Bytes per second   IOPS              
  Number of Reads  Number of Writes Data Read        Data Written      
---------------------------------------------------------------------------- 
CRS    00c0ff13349e000006d5c44f00000000 0B                 0                 
  45861            26756            3233.0MB         106.2MB 
DATA   00c0ff1311f300006dd7c44f00000000 2187.2KB           152               
  23220764         76411017         5506.3GB         1604.1GB 
DATA1  00c0ff1311f3000087d8c44f00000000 2295.2KB           154               
  23481442         78215540         5518.5GB         1602.6GB 
DATA2  00c0ff1311f30000c2f8ce5700000000 0B                 0                 
  26               4                1446.9KB         65.5KB 
FRA    00c0ff13349e000001d8c44f00000000 1829.3KB           14                
  3049951          15310681         1187.3GB         1941.2GB 
FRA1   00c0ff13349e000007d9c44f00000000 1872.8KB           14                
  3016521          15228157         1179.3GB         1939.5GB 
---------------------------------------------------------------------------- 
Success: Command completed successfully. 
Traceback (most recent call last): 
  File "./fetchSAN.py", line 34, in <module> 
    child.expect('# ') 
  File "/Library/Python/2.7/site-packages/pexpect-4.2.1-py2.7.egg/pexpect/spawnbase.py", line 321, in expect 
    timeout, searchwindowsize, async) 
  File "/Library/Python/2.7/site-packages/pexpect-4.2.1-py2.7.egg/pexpect/spawnbase.py", line 345, in expect_list 
    return exp.expect_loop(timeout) 
  File "/Library/Python/2.7/site-packages/pexpect-4.2.1-py2.7.egg/pexpect/expect.py", line 107, in expect_loop 
    return self.timeout(e) 
  File "/Library/Python/2.7/site-packages/pexpect-4.2.1-py2.7.egg/pexpect/expect.py", line 70, in timeout 
    raise TIMEOUT(msg) 
pexpect.exceptions.TIMEOUT: Timeout exceeded. 
<pexpect.pty_spawn.spawn object at 0x105333910> 
command: /usr/bin/ssh 
args: ['/usr/bin/ssh', '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="315c505f5056547100011f0304051f03061f0508" rel="noreferrer noopener nofollow">[email protected]</a>'] 
buffer (last 100 chars): '-------------------------------------------------------------\r\nPress any key to continue (Q to quit)' 
before (last 100 chars): '-------------------------------------------------------------\r\nPress any key to continue (Q to quit)' 
after: <class 'pexpect.exceptions.TIMEOUT'> 
match: None 
match_index: None 
exitstatus: None 
flag_eof: False 
pid: 19519 
child_fd: 5 
closed: False 
timeout: 30 
delimiter: <class 'pexpect.exceptions.EOF'> 
logfile: <open file 'FetchSan.log', mode 'w+' at 0x1053321e0> 
logfile_read: None 
logfile_send: None 
maxread: 2000 
ignorecase: False 
searchwindowsize: None 
delaybeforesend: 0.05 
delayafterclose: 0.1 
delayafterterminate: 0.1 
searcher: searcher_re: 
    0: re.compile("# ") 

这是日志中捕获的内容:

Password: mypassword 
 
 
HP StorageWorks MSA Storage P2000 G3 FC 
System Name: Uninitialized Name 
System Location:Uninitialized Location 
Version:TS230P008 
# show controller-statistics 
show controller-statistics 
Durable ID     CPU Load   Power On Time (Secs)   Bytes per second    
  IOPS             Number of Reads  Number of Writes Data Read         
  Data Written      
---------------------------------------------------------------------- 
controller_A   3          45962495               3803.1KB            
  73               386765821        514137947        6687.8GB          
  5748.9GB 
controller_B   20         45962413               5000.7KB            
  415              3208317860       587434274        63.9TB            
  5208.8GB 
---------------------------------------------------------------------- 
Success: Command completed successfully. 
 
# show vdisk-statistics 
show vdisk-statistics 
Name   Serial Number                    Bytes per second   IOPS              
  Number of Reads  Number of Writes Data Read        Data Written      
---------------------------------------------------------------------------- 
CRS    00c0ff13349e000006d5c44f00000000 0B                 0                 
  45861            26756            3233.0MB         106.2MB 
DATA   00c0ff1311f300006dd7c44f00000000 2187.2KB           152               
  23220764         76411017         5506.3GB         1604.1GB 
DATA1  00c0ff1311f3000087d8c44f00000000 2295.2KB           154               
  23481442         78215540         5518.5GB         1602.6GB 
DATA2  00c0ff1311f30000c2f8ce5700000000 0B                 0                 
  26               4                1446.9KB         65.5KB 
FRA    00c0ff13349e000001d8c44f00000000 1829.3KB           14                
  3049951          15310681         1187.3GB         1941.2GB 
FRA1   00c0ff13349e000007d9c44f00000000 1872.8KB           14                
  3016521          15228157         1179.3GB         1939.5GB 
---------------------------------------------------------------------------- 
Success: Command completed successfully. 
 
# show volume-statistics 
show volume-statistics 
Name        Serial Number                    Bytes per second    
  IOPS             Number of Reads  Number of Writes Data Read         
  Data Written      
---------------------------------------------------------------------- 
CRS_v001    00c0ff13349e0000fdd6c44f01000000 11.7KB              
  5                239609039        107145979        1321.0GB          
  110.5GB           
DATA1_v001  00c0ff1311f30000d0d8c44f01000000 2604.5KB            
  209              1701459941       336563041        33.9TB            
  3183.3GB          
DATA2_v001  00c0ff1311f3000040f9ce5701000000 0B                  
  0                921              15               2273.7KB          
  2114.0KB          
DATA_v001   00c0ff1311f30000bdd7c44f01000000 2382.8KB            
  194              1506859273       250871273        30.0TB            
  2025.4GB          
FRA1_v001   00c0ff13349e00001ed9c44f01000000 1923.5KB            
  31               25123006         161690520        1891.0GB          
  2229.1GB          
FRA_v001    00c0ff13349e00001fd8c44f01000000 2008.5KB            
  37               122050872        245301514        3475.7GB          
  3409.1GB          
---------------------------------------------------------------------- 
Press any key to continue (Q to quit)%  

请您参考如下方法:

作为起点:According to the manual ,SAN 有一个禁用寻呼机的命令。请参阅设置 cli-parameters pager off 的文档。执行该命令可能就足够了。它可能还有一个命令来设置用于格式化输出的终端行和列,尽管我找不到。

回答你的问题:当 ssh 客户端连接到服务器并请求交互式 session 时,它可以选择为 session 的服务器端请求 PTY(伪 tty)。当它执行此操作时,它会通知服务器服务器应用于 TTY 的行、列和终端类型。您的 SAN 可能会接受 PTY 请求并使用行和列值来格式化其输出。或者也可能不会。

ssh 客户端从 TTY 获取 PTY 请求的行和列作为其标准输入。这是 pexpect 用于与 ssh 通信的 PTY。 this question讨论如何设置 pexpect session 的终端大小。据我所知,ssh 不支持 LINES 或 COLUMNS 环境变量,所以我怀疑这是否有效。然而,calling child.setwinsize()生成后 ssh 应该可以工作:

child = pexpect.spawn(cmd) 
child.setwinsize(400,400) 

如果您遇到此问题,可以尝试在 ssh 之前通过在本地调用 stty 来设置终端大小:

child=pexpect.spawn('stty rows x cols y; ssh user@host') 

最后,您需要确保 ssh 确实为 session 请求 PTY。在某些情况下,它默认执行此操作,其中应该包括您运行它的方式。但它有一个命令行选项 -tt 来强制它分配 PTY。您可以将该选项添加到 ssh 命令行以确保:

child=pexpect.spawn('ssh -tt user@host') 
or 
child=pexpect.spawn('stty rows x cols y; ssh -tt user@host') 


评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!