【问题标题】:Popen command chaining returns 0 instead of 1Popen 命令链接返回 0 而不是 1
【发布时间】:2016-05-06 12:25:54
【问题描述】:

所以我是 Python 的新手。我正在做一个登录表单,它将您重定向到在 linux 服务器中运行的 python 脚本以验证用户身份。我一次使用多个命令来查看用户是否在数据库中。 命令是 echo "$password" |登录 -p -h 192.0.. $user >/dev/null 2>&1 当我回显 $?如果它在数据库中则返回 0,否则返回 1。

在 python 脚本中我有这个:

import cgi,shlex,subprocess

form = cgi.FieldStorage()

params={}

for key in form.keys():
   params[key]= form[key].value

user_name_variable=params['id']
password_variable=params['pwd']

command1="login -p -h 192.0. "+user_name_variable+" >/dev/null 2>&1"
command2="echo "+password_variable
command3="'echo $?'"
p1=subprocess.Popen(shlex.split(command2),shell=True,stdout=subprocess.PIPE)
p2=subprocess.Popen(shlex.split(command1),shell=True,stdin=p1.stdout, stdout=subprocess.PIPE)
p3=subprocess.Popen(shlex.split(command3),shell=True, stdin=p2.stdout, stdout=subprocess.PIPE)
p1.stdout.close()
p2.stdout.close()
out, err= p3.communicate()[0]

即使输入错误,out 也始终为 0。我用 PIPE 做错了什么吗?我所知道的是,问题不在于我传递变量时,因为我得到了正确的变量。问题一定出在链上。我会很感激你的帮助。谢谢。

【问题讨论】:

    标签: python linux subprocess popen


    【解决方案1】:

    好吧,这种方法在 bash 中也不起作用:

    false | echo $?  # echoes 0
    

    跳过p3,而不是p3.communicate,运行p2.communicate。之后,simply check p2.returncode

    【讨论】:

      【解决方案2】:

      $? 是一个 shell 变量,它在这里没有意义(每个子进程都在其自己的子 shell 中运行 shell=Truelogin 中的 $? 仅在其 shell 中可见,而不是那个你试试echo $? in)。

      但是Popen 对象已经提供了它们的退出状态,所以你根本不需要运行任何东西。您还试图使用 shlex.split 非法拆分带有 shell 元素的命令(您要么传递单个字符串和 shell=True,要么传递带有 shell=False 的参数序列;混合它们是非法的)。你也可以在这里减少很多进程,并避免运行在命令行中包含密码的命令:

      # Define command as a list directly; making a string and splitting it is silly
      command1 = ['login', '-p', '-h', '192.0.', user_name_variable]
      
      # Only need a single Popen; we can pass it stdin and read its status directly
      # As the shell command did, we throw away stdout and keep stderr
      p1=subprocess.Popen(command1, stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
      
      
      # Sends the password, closes proc stdin, waits for proc to complete slurping
      # the stderr (stdout was thrown away so it's returned empty)
      _, err = p1.communicate(password_variable)
      
      # Process is complete, so we can just ask for the return code
      if p1.returncode != 0:
           ... handle failed run ...
      

      注意:subprocess.DEVNULL 是 3.3 中的新内容;如果您使用的是旧版 Python,请替换:

      with open('/dev/null', 'wb') as devnull:
          p1 = subprocess.Popen(command1, stdin=subprocess.PIPE, stdout=devnull, stderr=subprocess.PIPE)
      

      或者只是将其更改为subprocess.PIPE 并忽略捕获的标准输出输出。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-01-05
        • 1970-01-01
        • 1970-01-01
        • 2017-04-03
        • 2016-06-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多