Popen命令链接返回0而不是1

时间:2016-01-28 22:14:59

标签: python linux subprocess popen

所以我是Python的新手。我正在进行登录表单,将您重定向到在Linux服务器上运行的python脚本以验证用户身份。我一次使用多个命令来查看用户是否在数据库中。 命令是echo“$ password”| login -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]
即使输入错误,

也会出现0。我在用PIPE做错了吗?我所知道的是,当我传递变量时问题不是因为我得到了正确的变量。问题必须在于链接。我很感激你的帮助。谢谢。

2 个答案:

答案 0 :(得分:3)

$?是一个shell变量,它在这里没有意义(每个子进程都在自己的子shell中运行shell=True;来自$?的{​​{1}}只是在shell中可见,而不是你尝试login的那个。)

但是echo $?对象已经提供了退出状态,因此您根本不需要运行任何东西。您还尝试使用Popen非法地将命令与shell元素分开(您传递单个字符串和shlex.split,或者使用shell=True传递一系列参数;混合它们是非法的) 。您也可以在这里节省大量进程,并避免在命令行中运行包含密码的命令:

shell=False

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

# 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 ...

或只是将其更改为with open('/dev/null', 'wb') as devnull: p1 = subprocess.Popen(command1, stdin=subprocess.PIPE, stdout=devnull, stderr=subprocess.PIPE) 并忽略捕获的标准输出。

答案 1 :(得分:0)

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

false | echo $?  # echoes 0

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