当输入停止时停止在远程服务器上跟踪文件使用 paramiko 和 Flask
Stop tailing a file on remote server when the input stops Using paramiko and Flask
我环顾四周,没有找到答案。
这是我的用例:
我在远程上有几个进程,这些进程是通过 python 脚本执行的,使用 paramiko 通过 ssh 连接到机器。我此时的问题是第一个脚本执行正常但由于 paramiko 的 tail 动作没有退出而挂起。下面是当前的相关代码。
建立 ssh 连接:
from paramiko_expect import SSHClientInteraction
def get_logs(appid, app):
try:
ssh = client.connect_ssh(IPADDRESS, USER)
interact = SSHClientInteraction(ssh, timeout=10, display=False)
interact.send('tail -f <Path to file>)
interact.tail(line_prefix=str(app)+': ')
except KeyboardInterrupt:
print('Ctrl+C interruption detected, stopping tail')
finally:
ssh.close()
有一个辅助函数没有显示,但这不是问题所在,所以我没有包括它。
主要应用程序代码的相关部分
@app.route('/processing', methods=['GET', 'POST'])
def processing():
form = InstitutionForm()
version_selected = form.versions.data
resp = make_response(render_template('processing.html', form=form))
sp_id = (request.cookies.get('sp_id').strip("[]").replace("L", ""), "SP")
rs_appid = (request.cookies.get('rs_base_id').strip("[]").replace("L", ""), "RS Base")
print "Undeploying"
for i in [rs_appid, sp_id]:
print i[0]
app_actions.undeploy(i[0].strip())
app_actions.get_logs(i[0].strip(), i[1])
while True:
time.sleep(10)
status = app_actions.check_status(i, "'undeploy'")[0][2]
print status
if status == 'failure':
print "undeploy failed"
break
elif status == 'success':
print "undeploy succeded"
break
else:
print "processing"
pass
所以我的问题是,当脚本通过 processing()
函数时,它开始显示 app_actions.get_logs()
调用所需的日志。之后它挂起。这似乎是因为 get_logs()
函数中的尾部调用没有结束。
我总结的问题是:
如何使用 paramiko 跟踪文件直到它停止然后退出并关闭 ssh 连接以便循环的下一部分可以 运行?
如果这个问题有任何错误或遗漏,我很抱歉,这是我在 SO
上提出的第一个问题
我会使用纯粹的 Python 来实现它,而不是使用 tail
。这是 Dan Beazy 关于发电机的演讲的一部分。
import time
def tail(fin):
fin.seek(0,2)
while True:
line = fin.readline()
if not line:
time.sleep(0.1)
continue
yield line
_fin = open("path/to/file","r")
lines = tail(_fin)
for line in lines:
print line,
所以eagle给出的答案是正确的,并为我指明了正确的方向,经过一番研究,我找到了更好的解决方案。此解决方案专门针对我正在使用的 paramiko_expect
库。您可以调用几个函数来跳出 tail
循环。
Here 是添加它们的拉取请求。
我个人使用 timeout
函数在没有收到输入后等待 15 秒以跳出循环。这非常适合我。
修改后的代码如下:
def get_logs(appid, app):
try:
ssh = client.connect_ssh(IPADDRESS, USER)
interact = SSHClientInteraction(ssh, timeout=10, display=False)
interact.send('tail -f <path to file>')
interact.tail(line_prefix=str(app) + ': ', timeout=15)
except KeyboardInterrupt:
print('Ctrl+C interruption detected, stopping tail')
except Exception:
ssh.close()
finally:
try:
ssh.close()
except:
pass
还要非常感谢 fotis 编写了一个很棒的模块,使我能够进行出色的自动化操作。
我环顾四周,没有找到答案。
这是我的用例:
我在远程上有几个进程,这些进程是通过 python 脚本执行的,使用 paramiko 通过 ssh 连接到机器。我此时的问题是第一个脚本执行正常但由于 paramiko 的 tail 动作没有退出而挂起。下面是当前的相关代码。
建立 ssh 连接:
from paramiko_expect import SSHClientInteraction
def get_logs(appid, app):
try:
ssh = client.connect_ssh(IPADDRESS, USER)
interact = SSHClientInteraction(ssh, timeout=10, display=False)
interact.send('tail -f <Path to file>)
interact.tail(line_prefix=str(app)+': ')
except KeyboardInterrupt:
print('Ctrl+C interruption detected, stopping tail')
finally:
ssh.close()
有一个辅助函数没有显示,但这不是问题所在,所以我没有包括它。
主要应用程序代码的相关部分
@app.route('/processing', methods=['GET', 'POST'])
def processing():
form = InstitutionForm()
version_selected = form.versions.data
resp = make_response(render_template('processing.html', form=form))
sp_id = (request.cookies.get('sp_id').strip("[]").replace("L", ""), "SP")
rs_appid = (request.cookies.get('rs_base_id').strip("[]").replace("L", ""), "RS Base")
print "Undeploying"
for i in [rs_appid, sp_id]:
print i[0]
app_actions.undeploy(i[0].strip())
app_actions.get_logs(i[0].strip(), i[1])
while True:
time.sleep(10)
status = app_actions.check_status(i, "'undeploy'")[0][2]
print status
if status == 'failure':
print "undeploy failed"
break
elif status == 'success':
print "undeploy succeded"
break
else:
print "processing"
pass
所以我的问题是,当脚本通过 processing()
函数时,它开始显示 app_actions.get_logs()
调用所需的日志。之后它挂起。这似乎是因为 get_logs()
函数中的尾部调用没有结束。
我总结的问题是:
如何使用 paramiko 跟踪文件直到它停止然后退出并关闭 ssh 连接以便循环的下一部分可以 运行?
如果这个问题有任何错误或遗漏,我很抱歉,这是我在 SO
上提出的第一个问题我会使用纯粹的 Python 来实现它,而不是使用 tail
。这是 Dan Beazy 关于发电机的演讲的一部分。
import time
def tail(fin):
fin.seek(0,2)
while True:
line = fin.readline()
if not line:
time.sleep(0.1)
continue
yield line
_fin = open("path/to/file","r")
lines = tail(_fin)
for line in lines:
print line,
所以eagle给出的答案是正确的,并为我指明了正确的方向,经过一番研究,我找到了更好的解决方案。此解决方案专门针对我正在使用的 paramiko_expect
库。您可以调用几个函数来跳出 tail
循环。
Here 是添加它们的拉取请求。
我个人使用 timeout
函数在没有收到输入后等待 15 秒以跳出循环。这非常适合我。
修改后的代码如下:
def get_logs(appid, app):
try:
ssh = client.connect_ssh(IPADDRESS, USER)
interact = SSHClientInteraction(ssh, timeout=10, display=False)
interact.send('tail -f <path to file>')
interact.tail(line_prefix=str(app) + ': ', timeout=15)
except KeyboardInterrupt:
print('Ctrl+C interruption detected, stopping tail')
except Exception:
ssh.close()
finally:
try:
ssh.close()
except:
pass
还要非常感谢 fotis 编写了一个很棒的模块,使我能够进行出色的自动化操作。