python中ioerror怎么解决_Python守护程序中的Paramiko导致IOError

我正在尝试使用

python守护进程内部的paramiko执行ssh命令.

当程序启动时,当paramiko尝试连接时,pycrypto会使用Bad文件描述符引发IOError.

如果我删除守护程序代码(只是取消注释最后一行并注释上面两个),则按预期建立ssh连接.

短测试程序的代码如下所示:

#!/usr/bin/env python2

from daemon import runner

import paramiko

class App():

def __init__(self):

self.stdin_path = '/dev/null'

self.stdout_path = '/dev/tty'

self.stderr_path = '/dev/tty'

self.pidfile_path = '/tmp/testdaemon.pid'

self.pidfile_timeout = 5

def run(self):

ssh = paramiko.SSHClient()

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

ssh.load_system_host_keys()

ssh.connect("hostname", username="username")

ssh.close()

app = App()

daemon_runner = runner.DaemonRunner(app)

daemon_runner.do_action()

#app.run()

跟踪看起来像这样:

Traceback (most recent call last):

File "./daemon-test.py", line 31, in

daemon_runner.do_action()

File "/usr/lib/python2.7/site-packages/daemon/runner.py", line 189, in do_action

func(self)

File "/usr/lib/python2.7/site-packages/daemon/runner.py", line 134, in _start

self.app.run()

File "./daemon-test.py", line 22, in run

ssh.connect("hostname", username="username")

File "/usr/lib/python2.7/site-packages/paramiko/client.py", line 311, in connect

t.start_client()

File "/usr/lib/python2.7/site-packages/paramiko/transport.py", line 460, in start_client

Random.atfork()

File "/usr/lib/python2.7/site-packages/Crypto/Random/__init__.py", line 37, in atfork

_UserFriendlyRNG.reinit()

File "/usr/lib/python2.7/site-packages/Crypto/Random/_UserFriendlyRNG.py", line 224, in reinit

_get_singleton().reinit()

File "/usr/lib/python2.7/site-packages/Crypto/Random/_UserFriendlyRNG.py", line 171, in reinit

return _UserFriendlyRNG.reinit(self)

File "/usr/lib/python2.7/site-packages/Crypto/Random/_UserFriendlyRNG.py", line 99, in reinit

self._ec.reinit()

File "/usr/lib/python2.7/site-packages/Crypto/Random/_UserFriendlyRNG.py", line 62, in reinit

block = self._osrng.read(32*32)

File "/usr/lib/python2.7/site-packages/Crypto/Random/OSRNG/rng_base.py", line 76, in read

data = self._read(N)

File "/usr/lib/python2.7/site-packages/Crypto/Random/OSRNG/posix.py", line 65, in _read

d = self.__file.read(N - len(data))

IOError: [Errno 9] Bad file descriptor

我猜这与守护进程产生时的流重定向有关.我试图将它们全部设置为/ dev / tty甚至是普通文件,但没有任何效果.

当我用strace运行程序时,我可以看到某些东西试图关闭一个文件两次,那是我收到错误的时候.但我无法找出描述符实际指向哪个文件(strace显示的内存位置似乎没有在任何地方设置).

最佳答案 这是我实际遇到的一个已知问题(这是导致我这个问题的原因).基本上,它与UNIX守护进程的定义以及paramiko实现其随机数生成器(RNG)的方式有关.

如果您参考PEP 3143 – Standard daemon process library,成为正确守护程序的第一步是“关闭所有打开的文件描述符”.不幸的是,这会将文件描述符关闭到/ dev / urandom,这是在加密模块的RNG中使用的,后者又由paramiko使用.

目前有一些解决方法,但作者表示他目前没有时间去处理这个错误(虽然第一个链接中的最后一篇文章是作者,截至本文撰写时为8天).

总之,如果在进程成为守护进程后导入paramiko,那么它应该按照需要工作,因为在守护进程关闭所有文件描述符之后将打开文件描述符.

用户@xraj也有一个hackish但聪明的解决方法,用于在守护进程时查找并保留文件描述符到/ dev / urandom(上面的第一个链接):

import os

from resource import getrlimit, RLIMIT_NOFILE

def files_preserve_by_path(*paths):

wanted=[]

for path in paths:

fd = os.open(path, os.O_RDONLY)

try:

wanted.append(os.fstat(fd)[1:3])

finally:

os.close(fd)

def fd_wanted(fd):

try:

return os.fstat(fd)[1:3] in wanted

except OSError:

return False

fd_max = getrlimit(RLIMIT_NOFILE)[1]

return [ fd for fd in xrange(fd_max) if fd_wanted(fd) ]

daemon_context.files_preserve = files_preserve_by_path('/dev/urandom')

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值