Paramiko / ssh / tail + grep 失效
情况:
我想通过ssh使用paramiko查看远程日志。
用命令channel.exec_command('tail -f log.log')可以正常工作。
但是用channel.exec_command('tail -f log.log | grep "filter" ')就卡住了。
我不明白为什么用grep的tail会卡住。
代码示例:
import paramiko
import select
import re
interesting_line_pattern = re.compile('xxx')
def do_tail():
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
from os.path import expanduser
home = expanduser("~")
client.connect('xxx',
username='xxx',
key_filename='%s/.ssh/id_rsa' % home)
log_file = '/home/xxx/log.log'
grep_pattern = "grep_filter"
remote_command = 'tail -f %s | grep "%s" ' % (log_file, grep_pattern)
print remote_command
transport = client.get_transport()
channel = transport.open_session()
channel.exec_command(remote_command)
while 1:
try:
rl, _, _ = select.select([channel], [], [], 0.0)
if len(rl) > 0:
print "ready to read"
for line in linesplit(channel):
print line
except (KeyboardInterrupt, SystemExit):
print 'got ctrl+c'
break
client.close()
print 'client closed'
def linesplit(socket):
buffer_string = socket.recv(4048)
done = False
while not done:
if "\n" in buffer_string:
(line, buffer_string) = buffer_string.split("\n", 1)
yield line + "\n"
else:
more = socket.recv(4048)
if not more:
done = True
else:
buffer_string = buffer_string + more
if buffer_string:
yield buffer_string
if __name__ == '__main__':
do_tail()
2 个回答
1
让我来分享一下适用于 Python 3.6 及以上版本的 linesplit 函数更新。
def linesplit(socket):
buffer_bytes = socket.recv(4048)
buffer_string = buffer_bytes.decode()
done = False
while not done:
if "\n" in buffer_string:
(line, buffer_string) = buffer_string.split("\n", 1)
yield line + "\n"
else:
more = socket.recv(4048)
if not more:
done = True
else:
buffer_string = buffer_string + more.decode()
if buffer_string:
yield buffer_string
10
grep
认为它没有在向终端输出,所以它在缓存输出内容。因为输入的内容没有足够的行匹配,所以它没有输出任何结果,这让你觉得它卡住了。
你可以试着给grep
加上--line-buffered
这个选项。比如:
channel.exec_command('tail -f log.log | grep --line-buffered "filter" ')