【问题标题】:How do I send a command to a CLI that has been opened as a subprocess?如何向已作为子进程打开的 CLI 发送命令?
【发布时间】:2014-07-03 10:54:54
【问题描述】:

我需要一些帮助。我想做的是用python程序打开一个子进程,然后让子进程在程序的某些点执行特定的命令。让我尝试用一​​个非常简单的代码 sn-p 来说明我的问题:

import subprocess
import time

#create a new terminal
cmd = ["gnome-terminal --window &"]
process = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE)

#do something else
time.sleep(5)

#and now I want to execute a command in the new terminal 

首先,我很高兴看到像lsifconfig 这样的简单命令起作用。只是在新终端中放置一些文本以确认它有效。

我曾希望 Popen.communicate(input) 能做到这一点,即类似于 process.communicate("ls") 的东西,但到目前为止它似乎不起作用。

任何帮助将不胜感激。

【问题讨论】:

    标签: python python-2.7 ubuntu subprocess


    【解决方案1】:

    您可能想查看 pexpect 模块 - 它正是为此目的而设计的,包括从您的子流程中查找特定提示和错误。

    我编写的脚本中的一个简单(精简)示例。它使用 ssh 会话登录并在服务器上运行脚本。

    import pexpect
    
    server = "server.home" # normally passed as arguments
    display = 1            # normally passed as arguments
    
    ssh = pexpect.spawn("ssh", ["{0}".format(server), "~/vnc.py", "{0}".format(display)])
    try:
        index = ssh.expect("^.*password:")
    except:
        print "Have not received password prompt from {host} - server down or ssh not enabled".format(host=server)
        sys.exit(1)
    
    if index == 0:   
        ssh.sendline( password )
    else:
        print "Unable to communicate with server"
    

    非常有用,尤其是当您有复杂的交互时。

    顺便说一句,完整的脚本是一组自制脚本,允许我在远程服务器上启动 VNC 服务器(作为打印服务器运行),然后将 vnc 查看器登录到 VNC 服务器。

    【讨论】:

      【解决方案2】:

      这是一个适用于 Windows 的函数。也许有帮助...

      Popen.communicate 正在处理该过程并在其结果中返回标准输出。我只能调用一次。如果我想发送多个命令,我需要将它们放在一个字符串中并在每个之后添加 \n。

      ## @ingroup cliFunc
      #  @brief run a commandline inside a shell
      #
      #  run a command in a console and return it's output
      #
      #  @param command   :[\b string] commandline to execute
      #  @param tempDir   :[\b string][\em optional] directory to run the command
      #  @return           [\b string] a string with the output
      def runCommandStdOut(command, tempDir = None):
          # redirect standard output (including the print statement)
          # creationflags for windows
          # CREATE_NO_WINDOW = 0x08000000
          p = sp.Popen("cmd.exe /X/D/F:ON", stdin=sp.PIPE,
                          stdout=sp.PIPE, stderr=sp.STDOUT, creationflags=0x08000000)
          flag = "(@@@@@@}"
          cmand = "PROMT"+flag+'\n'
      
          if tempDir:
          cmand +=  "cd " + tempDir +"\n"
      
      
          cmand += command
          return p.communicate(cmand+"\n")[0]
      

      【讨论】:

      • 感谢您的回答,但根据docs.python.org/2/library/subprocess.html,我应该使用“通信”而不是“标准输入”,或者? 警告使用communicate() 而不是.stdin.write、.stdout.read 或.stderr.read 来避免由于任何其他OS 管道缓冲区填满并阻塞子进程而导致的死锁。跨度>
      • 是的,我已经更新了我的示例。效果也很好,避免了文档中提到的阻塞。
      • 我建议在"ls"后面加\n。
      猜你喜欢
      • 2012-05-16
      • 2015-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多