Я пытаюсь отправить файл через WinRM / PowerShell, но мне кажется, что у меня ограничение в 3000 байт, и я не знаю, как от него избавиться.
Из локальной оболочки PowerShell, Я могу запустить эту команду и успешно отправить куски данных BASE64, я не ограничен:
while ($l=[System.Convert]::FromBase64String((Read-Host))){add-content -value ($l) -encoding byte -path 'tstfile.txt'}
Однако, если я пытаюсь отправить данные удаленно (из скрипта Python), передача запускается успешно исервер останавливается после того, как 3000 байт были записаны в tstfile.txt ...
Вот мой «упрощенный» код (Python 3.5.3 + pywinrm 0.3.0), вдохновленный Ansible (https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/connection/winrm.py):
import winrm
class TestUpload() :
def put_file(self, location, contents):
# start shell
self._shell_id = self._conn.open_shell()
ps_script='while ($l=[System.Convert]::FromBase64String((Read-Host))){add-content -value ($l) -encoding byte -path ' + location + '}'
command_id = self._conn.run_command(self._shell_id, "powershell -Command %s " % (ps_script))
# send data
b64contents = base64.b64encode(contents.encode('utf-8')).decode('ascii')
for i in range(0, len(b64contents), self._step):
self._raw_send_data(self._shell_id, command_id, b64contents[i:i+self._step] )
self._raw_send_data(self._shell_id, command_id, '', eof=True)
# close shell
self._conn.cleanup_command(self._shell_id, command_id)
self._conn.close_shell(self._shell_id)
def _raw_send_data(self, shell_id, command_id,content, eof=False):
req = {'env:Envelope': self._conn._get_soap_header(
resource_uri='http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd',
action='http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Send',
shell_id=shell_id)}
stream = req['env:Envelope'].setdefault('env:Body', {}).setdefault(
'rsp:Send', {}).setdefault('rsp:Stream', {})
stream['@CommandId'] = command_id
stream['@Name'] = 'stdin'
content += '\r\n'
stream['#text'] = base64.b64encode(content.encode('utf-8'))
stream['@xmlns:rsp'] = 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell'
if eof:
stream['@End'] = 'true'
res = self._conn.send_message(xmltodict.unparse(req))
Это работает:
t=TestUpload(step=100)
t.put_file('tstfile.txt',open('900bytesfile.txt').read())
Это не удается:
t=TestUpload(step=100)
t.put_file('tstfile.txt',open('9000bytesfile.txt').read())
Traceback (most recent call last):
File "/opt/environments/pypy/site-packages/winrm/transport.py", line 262, in _send_message_request
response.raise_for_status()
File "/opt/environments/pypy/site-packages/requests/models.py", line 940, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 500 Server Error: for url: https://win-srv1.local.activcloud.eu:5986/wsman
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/opt/environments/pypy/site-packages/winrm/protocol.py", line 234, in send_message
resp = self.transport.send_message(message)
File "/opt/environments/pypy/site-packages/winrm/transport.py", line 256, in send_message
response = self._send_message_request(prepared_request, message)
File "/opt/environments/pypy/site-packages/winrm/transport.py", line 273, in _send_message_request
raise WinRMTransportError('http', ex.response.status_code, response_text)
winrm.exceptions.WinRMTransportError: Bad HTTP response returned from server. Code 500
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/opt/repos/poc4/tst.py", line 158, in put_file
self._raw_send_data(self._shell_id, command_id, b64contents[i:i+self._step] )
File "/opt/repos/poc4/tst.py", line 332, in _raw_send_data
res = self._conn.send_message(xmltodict.unparse(req))
File "/opt/environments/pypy/site-packages/winrm/protocol.py", line 256, in send_message
raise WinRMOperationTimeoutError()
winrm.exceptions.WinRMOperationTimeoutError
У меня нет сообщений об ошибках (кроме времени ожидания), я не сделалничего не могу найти в логах сервера, единственная подсказка в том, что файл имеет длину 3000 байт на стороне сервера (данные внутри верны):
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 3/28/2019 2:52 PM 3000 tstfile.txt
У кого-нибудь есть идея? Может быть, проверитьесли ansible способен выполнить эту команду с более чем 3000 байтов данных?