如何设置pexpect ssh会话的列宽?

时间:2016-09-06 20:16:39

标签: python-2.7 ssh pexpect

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

我似乎遇到的问题是创建的SSH会话似乎限制为78个字符宽。每个命令生成的结果都要宽得多--155个字符。这引起了一堆愚蠢。

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

如何更改pexpect会话的列宽?

这是当前的代码(它有效但不完整):

#!/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.

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

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', 'manage@10.254.27.49']
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)% 

1 个答案:

答案 0 :(得分:1)

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

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

ssh客户端从TTY获取其标准输入的PTY请求的行和列。这是pexpect用来与ssh通信的PTY。 this question讨论了如何为pexpect会话设置终端大小。就我所知,Ssh并不尊重LINES或COLUMNS环境变量,所以我怀疑这会起作用。但是,产生ssh之后calling child.setwinsize()应该起作用:

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

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

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

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

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