过滤掉Python子进程模块中需要终端的命令

2023-12-25

我正在开发一个机器人,它接受来自网络(XMPP)的命令,并使用Python中的子进程模块来执行它们并发回命令的输出。本质上它是一个类似 SSH 的基于 XMPP 的非交互式 shell。

机器人仅执行来自经过身份验证的可信源的命令,因此允许任意 shell 命令(shell=True).

然而,当我不小心发送一些需要 tty 的命令时,机器人被卡住了。

例如:

subprocess.check_output(['vim'], shell=False)
subprocess.check_output('vim', shell=True)

如果收到上述每个命令,机器人就会被卡住,并且运行机器人的终端就会损坏。

尽管机器人只接收来自经过身份验证的可信来源的命令,但人类还是会犯错。我怎样才能让机器人过滤掉那些会破坏自身的命令?我知道有os.isatty但我该如何利用它呢?有没有办法检测那些“坏”命令并拒绝执行它们?

TL;DR:罢工>

比如说,有两种命令:

  • 命令如ls: 不需要 tty 来运行。
  • 命令如vim: 需要一个 tty;如果没有给出 tty,则中断子进程。

我怎么知道一个命令是ls- 类似或是vim-like 并拒绝运行命令(如果是)vim-like?


您期望的是一个接收命令作为输入并返回的函数有意义的通过运行命令输出。

由于命令是任意的,对 tty 的要求只是可能发生的许多不良情况之一(其他包括运行无限循环),您的函数应该只关心它的运行周期,换句话说,命令是“坏”还是不应该取决于它是否在有限时间内结束,并且因为subprocess本质上是异步的,您可以只运行命令并在更高的视野中处理它。

演示代码播放,可以更改cmd值来看看它的表现有何不同:

#!/usr/bin/env python
# coding: utf-8

import time
import subprocess
from subprocess import PIPE


#cmd = ['ls']
#cmd = ['sleep', '3']
cmd = ['vim', '-u', '/dev/null']

print 'call cmd'
p = subprocess.Popen(cmd, shell=True,
                     stdin=PIPE, stderr=PIPE, stdout=PIPE)
print 'called', p

time_limit = 2
timer = 0
time_gap = 0.2

ended = False
while True:
    time.sleep(time_gap)

    returncode = p.poll()
    print 'process status', returncode

    timer += time_gap
    if timer >= time_limit:
        print 'timeout, kill process'
        p.kill()
        break

    if returncode is not None:
        ended = True
        break

if ended:
    print 'process ended by', returncode

    print 'read'
    out, err = p.communicate()
    print 'out', repr(out)
    print 'error', repr(err)
else:
    print 'process failed'

上述代码中值得注意的三点:

  1. We use Popen代替check_output运行命令,与check_output这将等待该过程结束,Popen立即返回,因此我们可以做进一步的事情来控制过程。

  2. 我们实现一个计时器来检查进程的状态,如果它运行太长时间,我们手动杀死它,因为我们认为如果一个进程不能在有限的时间内结束,它就没有意义。这样你原来的问题就解决了,如下vim永远不会结束,它肯定会被作为一个“无意义”的命令而被杀死。

  3. 定时器帮助我们过滤掉坏命令后,我们可以通过调用来获取命令的stdout和stderrcommunicate的方法Popen对象,之后您可以选择确定返回给用户的内容。

结论

不需要tty模拟,我们应该异步运行子进程,然后通过定时器控制它来确定是否应该杀死它,对于正常结束的,它是安全且容易获得输出的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

过滤掉Python子进程模块中需要终端的命令 的相关文章

  • Lighttpd 和 cgi python

    我正在尝试通过 lighttpd 执行一些 python 脚本 但是当我尝试运行它时 我只得到一个要求我下载的空白文件 lighttpd conf server modules mod access mod alias mod access
  • 中断 Select 以添加另一个要在 Python 中监视的套接字

    我正在 Windows XP 应用程序中使用 TCP 实现点对点 IPC 我正在使用select and socketPython 2 6 6 中的模块 我有三个 TCP 线程 一个读取线程通常会阻塞select 一个通常等待事件的写入线程
  • Django 的内联管理:一个“预填充”字段

    我正在开发我的第一个 Django 项目 我希望用户能够在管理中创建自定义表单 并向其中添加字段当他或她需要它们时 为此 我在我的项目中添加了一个可重用的应用程序 可在 github 上找到 https github com stephen
  • 将html数据解析成python列表进行操作

    我正在尝试读取 html 网站并提取其数据 例如 我想查看公司过去 5 年的 EPS 每股收益 基本上 我可以读入它 并且可以使用 BeautifulSoup 或 html2text 创建一个巨大的文本块 然后我想搜索该文件 我一直在使用
  • 需要在python中找到print或printf的源代码[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我正在做一些我不能完全谈论的事情 我
  • 删除flask中的一对一关系

    我目前正在使用 Flask 开发一个应用程序 并且在删除一对一关系中的项目时遇到了一个大问题 我的模型中有以下结构 class User db Model tablename user user id db Column db String
  • 独立滚动矩阵的行

    我有一个矩阵 准确地说 是 2d numpy ndarray A np array 4 0 0 1 2 3 0 0 5 我想滚动每一行A根据另一个数组中的滚动值独立地 r np array 2 0 1 也就是说 我想这样做 print np
  • 使用字典映射数据帧索引

    为什么不df index map dict 工作就像df column name map dict 这是尝试使用index map的一个小例子 import pandas as pd df pd DataFrame one A 10 B 2
  • YOLOv8获取预测边界框

    我想将 OpenCV 与 YOLOv8 集成ultralytics 所以我想从模型预测中获取边界框坐标 我该怎么做呢 from ultralytics import YOLO import cv2 model YOLO yolov8n pt
  • 如何将张量流模型部署到azure ml工作台

    我在用Azure ML Workbench执行二元分类 到目前为止 一切正常 我有很好的准确性 我想将模型部署为用于推理的 Web 服务 我真的不知道从哪里开始 azure 提供了这个doc https learn microsoft co
  • “隐藏”内置类对象、函数、代码等的名称和性质[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我很好奇模块中存在的类builtins无法直接访问的 例如 type lambda 0 name function of module
  • 在Python中检索PostgreSQL数据库的新记录

    在数据库表中 第二列和第三列有数字 将会不断添加新行 每次 每当数据库表中添加新行时 python 都需要不断检查它们 当 sql 表中收到的新行数低于 105 时 python 应打印一条通知消息 警告 数量已降至 105 以下 另一方面
  • 如何通过 TLS 1.2 运行 django runserver

    我正在本地 Mac OS X 机器上测试 Stripe 订单 我正在实现这段代码 stripe api key settings STRIPE SECRET order stripe Order create currency usd em
  • pip 列出活动 virtualenv 中的全局包

    将 pip 从 1 4 x 升级到 1 5 后pip freeze输出我的全局安装 系统 软件包的列表 而不是我的 virtualenv 中安装的软件包的列表 我尝试再次降级到 1 4 但这并不能解决我的问题 这有点类似于这个问题 http
  • 如何使用原始 SQL 查询实现搜索功能

    我正在创建一个由 CS50 的网络系列指导的应用程序 这要求我仅使用原始 SQL 查询而不是 ORM 我正在尝试创建一个搜索功能 用户可以在其中查找存储在数据库中的书籍列表 我希望他们能够查询 书籍 表中的 ISBN 标题 作者列 目前 它
  • Python:XML 内所有标签名称中的字符串替换(将连字符替换为下划线)

    我有一个格式不太好的 XML 标签名称内有连字符 我想用下划线替换它 以便能够与 lxml objectify 一起使用 我想替换所有标签名称 包括嵌套的子标签 示例 XML
  • python import inside函数隐藏现有变量

    我在我正在处理的多子模块项目中遇到了一个奇怪的 UnboundLocalError 分配之前引用的局部变量 问题 并将其精简为这个片段 使用标准库中的日志记录模块 import logging def foo logging info fo
  • Python ImportError:无法导入名称 __init__.py

    我收到此错误 ImportError cannot import name life table from cdc life tables C Users tony OneDrive Documents Retirement retirem
  • 更改 Tk 标签小部件中单个单词的颜色

    我想更改 Tkinter 标签小部件中单个单词的字体颜色 我知道可以使用文本小部件来实现与我想要完成的类似的事情 例如使单词 YELLOW 显示为黄色 self text tag config tag yel fg clr yellow s
  • cv2.VideoWriter:请求一个元组作为 Size 参数,然后拒绝它

    我正在使用 OpenCV 4 0 和 Python 3 7 创建延时视频 构造 VideoWriter 对象时 文档表示 Size 参数应该是一个元组 当我给它一个元组时 它拒绝它 当我尝试用其他东西替换它时 它不会接受它 因为它说参数不是

随机推荐