【问题标题】:How do I set the column width of a pexpect ssh session?如何设置 pexpect ssh 会话的列宽?
【发布时间】:2016-09-06 20:16:38
【问题描述】:

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

我似乎遇到的问题是,所创建的 SSH 会话似乎被限制为 78 个字符宽。每个命令生成的结果明显更宽 - 155 个字符。这引起了一堆时髦。

首先,当前状态下的结果更难解析。其次,由于缓冲区明显更小,最终的音量命令将无法正确执行,因为 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.

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

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)% 

【问题讨论】:

    标签: python-2.7 ssh pexpect


    【解决方案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 环境变量,所以我怀疑这会起作用。但是,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 确实为会话请求 PTY。在某些情况下,它默认执行此操作,这应该包括您运行它的方式。但是它有一个命令行选项-tt 来强制它分配一个PTY。您可以将该选项添加到 ssh 命令行以确保:

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

    【讨论】:

    • 这些建议效果很好。该脚本现在正在嗡嗡作响,没有任何问题。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2011-05-05
    • 1970-01-01
    • 2020-06-23
    • 1970-01-01
    • 2011-03-28
    • 2011-01-10
    • 2012-01-11
    • 1970-01-01
    相关资源
    最近更新 更多