【问题标题】:Python subprocess change dir via client/serverPython子进程通过客户端/服务器更改目录
【发布时间】:2015-07-11 13:40:09
【问题描述】:

我正在尝试通过现有客户端上的套接字库远程更改 cwd,但每次发送实际命令“cd ..”时都会遇到麻烦。

服务器:

import socket, subprocess, os, sys

s = socket.socket()

host = socket.gethostname()
ip = socket.gethostbyname(host)
port = 8080

s.bind((ip,port))
s.listen(5)

c, a = s.accept()

fr = c.recv(10000)

cwd = fr

print("IP: "+str(a[0])+":"+str(a[1])+"\tCONNECTED")

while True:
    cmd = raw_input("\n"+cwd+"> ")
    if cmd != "":
        c.sendall(cmd)
        data = c.recv(1024)
        print("\n"+data)

    if cmd == "cd ..":
        c.sendall(cmd)
        cwd = c.recv(1024)

客户:

import socket, subprocess, os, sys



i = 1



cwd = os.getcwd()

while 1:
    s = socket.socket()
    host = socket.gethostname()
    ip = socket.gethostbyname(host)
    port = 8080

    try:
        s.settimeout(5)
        s.connect((ip,port))
        s.settimeout(None)
        s.sendall(cwd)

        i = 1

        while i == 1:
            cmd = s.recv(10000)
            if cmd != "over":
                sp = subprocess.Popen(cmd, shell=True, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
                out = sp.stdout.read()+"_________________________________"
                msg = out + sp.stderr.read()
                s.sendall(msg)
            if cmd == "over":
                s.close()
                i = 0

            if cmd == "cd ..":
                j = 0
                k = 0
                for i in cwd:
                    if i == '/':
                        k = j
                    j = j + 1
                cd = cwd[0:k]
                subprocess.Popen('echo', shell=True, cwd=cd)
                s.sendall(cd)

                print(cd)


    except socket.error:
        continue

这是我得到的错误:

Traceback (most recent call last):
  File "PycharmProjects/server-client/test_hq.py", line 25, in <module>
    c.sendall(cmd)
  File "/usr/lib/python2.7/socket.py", line 228, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 104] Connection reset by peer

我无法弄清楚似乎是什么问题......

【问题讨论】:

  • 我真的不明白你想说什么
  • cmd和这个有什么关系?
  • 这里的cmd只指向我写的程序
  • 你不是想在 cd 之后获取路径吗?这个循环完全没有意义。你也在从服务器发送和接收吗?
  • 嗯,对不起。我不小心跳过了这部分。我在当前路径(cwd)中检查“/”,当它到达最后一个“/”时,它会保存位置并将当前部分从第一个字符重写为保存的部分(`cd = cwd[0:k]`部分)

标签: python sockets python-2.7


【解决方案1】:

这应该更接近你想要的,一次接收和发送一次,而不是重复发送和接收相同的命令要简单得多:

客户端.py:

import socket, subprocess, os, sys

cwd = os.getcwd()

def make_socket():
    s = socket.socket()
    host = socket.gethostname()
    ip = socket.gethostbyname(host)
    port = 8080
    s.settimeout(5)
    s.connect((ip, port))
    s.settimeout(None)
    s.sendall(cwd)
    return s

while True:
    s = make_socket()
    try:
        while True:
            cmd = s.recv(10000)
            if cmd == "cd ..":
                # os.chdir("..") # uncomment to actually change directory
                cd = cwd.rsplit(os.sep(), 1)[0]
                subprocess.Popen('echo', shell=True, cwd=cd)
                s.sendall(cd)
            elif cmd != "over":
                sp = subprocess.Popen(cmd, shell=True, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                      stdin=subprocess.PIPE)
                out = sp.stdout.read() + "_________________________________"
                msg = out + sp.stderr.read()
                s.sendall(msg)
            else:
                print("closed")
                s.close()
                sys.exit(0)
    except socket.error as e:
        print(e)
        break

server.py:

import socket, subprocess, os, sys

s = socket.socket()

host = socket.gethostname()
ip = socket.gethostbyname(host)
port = 8080

s.bind((ip,port))
s.listen(5)

c, a = s.accept()

fr = c.recv(10000)

cwd = fr

print("IP: "+str(a[0])+":"+str(a[1])+"\tCONNECTED")

while True:
    cmd = raw_input("\n"+cwd+"> ")
    if cmd == "cd ..":
        print("sending 2")
        c.sendall(cmd)
        # os.chdir("..") # uncomment to change dir
        cwd = c.recv(10000)
    elif cmd != "":
        print("sending 1")
        c.sendall(cmd)
        data = c.recv(10000)
        print("\n"+data)

如果您想在服务器端处理客户端关闭套接字和 sys.exit(0),您应该在服务器端捕获 socket.error 以避免管道损坏错误。

try:
    while True:
        print(os.getcwd(),44444)
        cmd = raw_input("\n"+cwd+"> ")
        if cmd != "" and cmd != "cd ..":
            print("sending 1")
            c.sendall(cmd)
            data = c.recv(10000)
            print("\n"+data)
        if cmd == "cd ..":
            print("sending 2")
            c.sendall(cmd)
            # os.chdir("..") # uncomment to change dir
            cwd = c.recv(10000)
except socket.error as e:
    print("Exception caught for {}".format(e.strerror))

如果你想根据 errno 做不同的事情,你可以在 except 中进行比较:

if e.errno == errno.EPIPE: 即断管等。

errno docs 中列出了所有 errno

【讨论】:

    【解决方案2】:

    考虑到评论,这可能有助于解决您的cd 问题:

    import re
    import os.path
    
    # Other stuff
    
            m = re.match(r'cd(?:\s+|$)(.*)', cmd)
            if m:
                dirs = m.groups()
    
                # Default to cd is home directory
                if len(dirs) == 0 or len(dirs[0]) == 0:
                    dir = os.environ['HOME']
                else:
                    dir = dirs[0]
                    if dir == '..':
                        head, tail = os.path.split(cwd)
                        dir = head
    
                subprocess.Popen('echo', shell=True, cwd=dir)
    
                s.sendall(dir)
    
                # Update cwd
                cwd = dir
    
                print(dir)
            else:
                # Some other command
    

    【讨论】:

    • over 发送一个 sys.exit() 命令,基本上。服务器关闭与客户端的连接。我需要客户端随时待命,所以在这种情况下,我需要它在循环中(即使它无法连接或抛出套接字错误,我也需要它继续尝试)。用cd ..我想去当前shell的子目录,我卡住了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-27
    • 2012-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多