【问题标题】:Pipe ssh session into and out of python通过管道将 ssh 会话导入和导出 python
【发布时间】:2018-04-06 21:52:25
【问题描述】:

我工作的公司使用过时的信息系统(版权所有 1991-2001)。该系统是一台运行 ssh 服务器的 Centos 机器。无法以任何方式访问后端或其数据。所有数据都需要通过文本报告检索,或通过手动按键输入。这是您登录时看到的example

我正在尝试编写一个 python 脚本,该脚本将模拟击键以运行报告和执行琐碎的任务。我已经使用 Windows 上的 .cmd 文件成功完成了这项工作,该文件连接并模拟了击键。问题是有些进程具有不可预测的分支(有时会弹出一条消息并要求提供一些信息或按键以验证您是否看到了一条消息)。我可以预测分支可能发生的位置,但无法检测它是否真的存在,因为我的 .cmd 文件对 ssh 会话的输出是盲目的。 (顺便说一下,我在 windows 下工作)

我想做的是使用一个 python 脚本,它使用标准输入并根据它看到的内容做出决定,但我对管道的工作方式不熟悉。插入我的脚本有效,但我不确定如何将击键从 python 脚本发送回 ssh 会话。这是我的测试脚本的一个示例:

import sys
import time

buff=''
try:
    while True:
        buff += sys.stdin.read(1)
        if buff[-5:] == 'press':
            print('found word "press"!')
            #Send a keystroke back to the ssh session here
            buff = ''
except KeyboardInterrupt:
    sys.stdout.flush
    pass

我是这样称呼它的:

ssh MyUsername@###.###.###.### | python -u pipe_test.py

当它运行时,我什么都看不到,但我已经验证我可以使用我的常规键盘通过终端发送击键。

关于如何将击键输出到 ssh 会话的任何想法? 我应该做一些完全不同、更简单的事情吗?

仅供参考:服务器发送到终端的数据有 ASCII 转义字符到处乱飞。这不是一个很好的 bash 界面或类似的东西。此外,我还安装了一堆 Unix 命令行工具,例如,我可以从 windows 进行 ssh。

tl;dr 如何从 ssh 会话通过管道传输到 python,并从同一个 python 脚本将击键发送回 ssh 会话?

【问题讨论】:

  • 这可能值得研究pexpect。您将从 Python 生成 ssh 进程,而不是通过管道传输标准输入/输出。
  • 哇,谢谢。我今天才刚刚开始研究这个,但看起来它会起作用!一旦我得到一些工作,我会用一个示例脚本来回答这个问题

标签: python windows pipe pipeline


【解决方案1】:

你绝对不能用管道来做这件事。 Unix 管道是一种单向的进程间通信机制。您可以向它发送数据,也可以从中读取数据。但不是两者都(通过同一管道)。

可以使用成对的管道来创建协同进程。这甚至在某些 Unix shell(例如 Korn shell 和 Bash 版本 4 (https://www.gnu.org/software/bash/manual/html_node/Coprocesses.html) 中直接支持。但是这种机制有些脆弱并且容易出现死锁。只要这对双方的进程都可以工作。的管道在处理管道和相关的缓冲方面是严格的(实际上可能只有一端是严格的,但即使这样也很棘手)。对于您尝试运行的程序而言,情况不太可能如此远程。

有人建议pexpect,这是控制本地生成的终端或诅咒应用程序的绝佳选择。通过生成本地 ssh 客户端并对其进行控制,可以使用它来管理远程进程。

但是,从 Python 访问 ssh 协议和 API 的更好选择是 Paramiko。这实现了 ssh 协议,因此您可以作为 API 访问远程 sshd 进程,而不是通过客户端(命令行实用程序)。

这种方法的一个优点是您可以以编程方式管理端口重定向、传输和管理文件(就像使用 sftp 一样)(包括设置权限等),并且您可以单独执行程序和访问它们的标准输入、输出和错误流或它们的伪终端 (pty),以及获取远程进程的退出代码,与本地 ssh 客户端的退出代码不同。

甚至还有一个包paramiko-expect 为Paramiko 添加了一个扩展,以便更直接地使用这些远程pty 对象。 (Pexpect 在 pty 控制本地进程上提供了类似的功能)。 [警告:我还没用过 Fotis Gimian 的包;但我已经相当广泛地使用了 Paramiko,有时希望我有类似的东西]。

您可能已经从这个答案中了解到,在 Unix(Linux 或其任何变体)下以编程方式处理交互式终端/文本程序的复杂性与该程序的编写方式有关。

某些程序,例如 shell,可以完全由面向行的输入和输出驱动到它们的标准文件描述符(stdin、stdout 和 stderr)。其他人必须通过他们的终端接口来控制(这是通过使用伪终端环境启动它们来完成的......例如 sshd 在启动正常交互过程时提供的环境,以及由expect(以及 pexect 以及受旧 TCL/expect 启发的各种其他模块和实用程序)和您的 xterm或任何现代操作系统下的其他终端窗口程序(甚至包括最新版本的 Microsoft Windows 下的 Cygwin 或“Windows 的 Bash”或 WSL(Windows 支持 Linux))。

一般来说,您的尝试将需要使用一种或另一种方法,而管道对于使用标准文件描述符的方法仅非常粗略有用。使用哪种方法的决定主要取决于您尝试(远程)控制的程序。

【讨论】:

    猜你喜欢
    • 2016-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-10
    • 2014-08-25
    • 2016-09-26
    • 1970-01-01
    相关资源
    最近更新 更多