- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 paramiko 收集有关远程主机的一些信息并遇到问题,在读取 (read()
/readline()
/readlines( )
) 来自 stderr
channel 。
有时 stderr.read()
会返回一个空字符串,对我来说这看起来像是竞争条件的结果。但是,根据我在 Internet 上找到的文档和示例,这似乎是正确的方法。
我还尝试打开一个专用 channel 并利用 chan.recv_ready()
/chan.recv_stderr_ready()
并通过循环从各个 channel 读取 chan.recv()
/chan.recv_stderr()
但是会导致相同的行为。
这是一个最小的测试用例 - 在我的设置中 - 可靠地导致了该行为。
import paramiko
class SSH:
def __init__(self):
self.ssh = paramiko.SSHClient()
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.ssh.connect('127.0.0.1', port=31337, username='root', password='root')
self.stdout = ''
self.stderr = ''
self.exit_code = 0
def _run_cmd(self, cmd):
self.stdout = ''
self.stderr = ''
stdin, stdout, stderr = self.ssh.exec_command(cmd)
self.stdout = stdout.read()
self.stderr = stderr.read()
while not stdout.channel.exit_status_ready():
pass
self.exit_code = stdout.channel.recv_exit_status()
if self.exit_code:
print("ERROR: " + self.stderr)
def process_list(self):
self._run_cmd('ls /proc/ | grep -E "^[0-9]+$" | grep -v $$')
lines = self.stdout.split('\n')[:-1]
data = []
for process in lines:
process_data = {}
process_data['pid'] = int(process)
# fetching and parsing process status information from /proc/[PID]/status
self._run_cmd('cat /proc/%d/status' % (int(process)))
data.append(self.stdout)
return data
data = SSH()
while True:
print data.process_list()
经过几次运行(如果不是第一次)我得到的是:
虽然我期待:
错误:
错误:cat:/proc/12883/status:没有那个文件或目录
如何确保 stderr 已准备好读取/我读取了 stderr 上的所有数据?
最佳答案
长话短说:我遇到过这些问题中的大多数,并且针对我的大多数 ssh 相关问题提出了最终解决方案。因此,请随时查看 this exec_command
的实现避免了大多数 empty_response/stalling 场景。
说来话长
这里的主要问题是您的 exec_command()
是非阻塞的,并且生成一个负责 channel 通信的线程。该线程正在等待传入数据并将其放入 channel 缓冲区,而主线程可能会继续运行。这就是你的问题所在。您读取缓冲区的时间过早,甚至在您检查您的一方是否收到 exit_status
之前。收到 exit_status
确认远程进程以给定的状态代码退出。收到远程状态代码并不表示您已收到可能仍在传输中的所有数据。它甚至可能乱序到达你身边,说 status_code
可能甚至在所有数据之前到达(stderr
,stdout
)收到了。
当数据到达时,主线程继续。在您的情况下,主线程尝试从 stdout
和 stderr
读取一次,然后阻塞直到 exit_status
准备就绪。请注意, channel 线程可能仍会从您的远程命令调用接收数据。另请注意,一旦您的一方收到远程 exit_status
,您将必须手动清空缓冲区。
在您的特定情况下,会发生这种情况:
execute_command
生成一个新线程(调用 id exec_thread,管理远程命令调用stdout
、stderr
缓冲区的当前 内容存储在self.stdout
,self.stderr
。请注意,您不知道是否收到了 stderr
或 stdout
的所有数据。您很可能刚刚收到了一些 block 。stdout
、stderr
接收数据,而 [main-thread] 继续。exit_status
。再次注意,此时您的缓冲区可能仍然充满了最近收到的 stderr
、stdout
block 。exit_status
存储在self.exit_code
中。 [exec_thread] 仍然存在,可能仍会收到一些乱序数据。输入缓冲区可能仍处于填充状态。run_cmd
返回请注意,该 channel 的 [exec_thread] - paramiko 为每个 channel 调用创建一个线程(即 exec_command
) - 仍然存在,它们会一直闲置并产生问题,直到您手动关闭它们(stdout.channel.close()
).
关于python - 标准错误上的 Paramiko recv()/read()/readline(s)() 返回空字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33708336/
我正在尝试创建一个程序,其中字符串的前三个字符重复给定次数,如下所示: foo('Chocolate', 3) # => 'ChoChoCho' foo('Abc', 3) # => 'AbcAbcA
我有以下字符串: std::string str = "Mode:AAA:val:101:id:A1"; 我想分离一个位于 "val:" 和 ":id" 之间的子字符串,这是我的方法: std::st
DNA 字符串可以是任意长度,包含 5 个字母(A、T、G、C、N)的任意组合。 压缩包含 5 个字母(A、T、G、C、N)的 DNA 字母串的有效方法是什么?不是考虑每个字母表 3 位,我们可以使用
是否有一种使用 levenstein 距离将一个特定字符串与第二个较长字符串中的任何区域进行匹配的好方法? 例子: str1='aaaaa' str2='bbbbbbaabaabbbb' if str
使用 OAuth 并使用以下函数使用我们称为“foo”(实际上是 OAuth token )的字符串加密 key public function encrypt( $text ) { // a
我是一名优秀的程序员,十分优秀!