所以我是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做错了吗?我所知道的是,当我传递变量时问题不是因为我得到了正确的变量。问题必须在于链接。我很感激你的帮助。谢谢。
答案 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
。