Popen 命令链接 returns 0 而不是 1

Popen command chaining returns 0 instead of 1

所以我是 Python 的新人。我正在做一个登录表单,将您重定向到 linux 服务器中的 python 脚本 运行 以验证用户。我一次使用多个命令来查看用户是否在数据库中。 命令是 echo "$password" |登录-p -h 192.0.. $用户 >/dev/null 2>&1 当我回应 $?它应该 return 如果它在数据库中则为 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 做的有什么问题吗?我所知道的是,问题不在于我传递变量时,因为我得到了正确的变量。问题一定出在链接中。我将不胜感激你的帮助。谢谢。

嗯,这种方法在 bash 中不起作用,或者:

false | echo $?  # echoes 0

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

$? 是一个 shell 变量,它在这里没有意义(每个子进程在其自己的子 shell 和 shell=True 中是 运行 ; 来自 login$? 仅在其 shell 中可见,而不是您尝试在 echo $? 中看到的那个。

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

# 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 并忽略捕获的标准输出输出。