From c90eed1c8a7a8504e543b04c0c1184289b8e8619 Mon Sep 17 00:00:00 2001 From: vapao Date: Mon, 8 Nov 2021 14:26:04 +0800 Subject: [PATCH] =?UTF-8?q?U=20=E4=BC=98=E5=8C=96ssh=E7=B1=BB=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spug_api/libs/ssh.py | 45 ++++++++++++++++++++++----------------- spug_api/requirements.txt | 2 +- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/spug_api/libs/ssh.py b/spug_api/libs/ssh.py index d1ad6d1..1fbd3a4 100644 --- a/spug_api/libs/ssh.py +++ b/spug_api/libs/ssh.py @@ -18,6 +18,7 @@ class SSH: self.channel = None self.sftp = None self.eof = 'Spug EOF 2108111926' + self.already_init = False self.default_env = self._make_env_command(default_env) self.regex = re.compile(r'Spug EOF 2108111926 (-?\d+)[\r\n]?') self.arguments = { @@ -63,11 +64,7 @@ class SSH: channel.set_combine_stderr(True) channel.exec_command(command) code, output = channel.recv_exit_status(), channel.recv(-1) - try: - output = output.decode() - except UnicodeDecodeError: - output = output.decode(encoding='GBK') - return code, output + return code, self._decode(output) def exec_command(self, command, environment=None): channel = self._get_channel() @@ -94,9 +91,9 @@ class SSH: stdout = channel.makefile("rb", -1) out = stdout.readline() while out: - yield channel.exit_status, out.decode() + yield channel.exit_status, self._decode(out) out = stdout.readline() - yield channel.recv_exit_status(), out.decode() + yield channel.recv_exit_status(), self._decode(out) def exec_command_with_stream(self, command, environment=None): channel = self._get_channel() @@ -104,7 +101,7 @@ class SSH: channel.send(command) exit_code, line = -1, '' while True: - line = channel.recv(8196).decode() + line = self._decode(channel.recv(8196)) if not line: break match = self.regex.search(line) @@ -127,6 +124,10 @@ class SSH: sftp = self._get_sftp() return sftp.listdir_attr(path) + def sftp_stat(self, path): + sftp = self._get_sftp() + return sftp.stat(path) + def remove_file(self, path): sftp = self._get_sftp() sftp.remove(path) @@ -137,14 +138,14 @@ class SSH: counter = 0 self.channel = self.client.invoke_shell() - command = 'export PS1= && stty -echo; unsetopt zle; set -e\n' + command = 'set +o zle\nset -o no_nomatch\nexport PS1= && stty -echo\n' if self.default_env: command += f'{self.default_env}\n' command += f'echo {self.eof} $?\n' self.channel.send(command.encode()) while True: if self.channel.recv_ready(): - line = self.channel.recv(8196).decode() + line = self._decode(self.channel.recv(8196)) if self.regex.search(line): self.stdout = self.channel.makefile('r') break @@ -163,11 +164,6 @@ class SSH: self.sftp = self.client.open_sftp() return self.sftp - def _break(self): - time.sleep(5) - command = f'\x03 echo {self.eof} -1\n' - self.channel.send(command.encode()) - def _make_env_command(self, environment): if not environment: return None @@ -181,18 +177,29 @@ class SSH: return f'export {str_envs}' def _handle_command(self, command, environment): - new_command = f'trap \'echo {self.eof} $?; rm -f $SPUG_EXEC_FILE\' EXIT\n' + new_command = commands = '' + if not self.already_init: + commands = 'export SPUG_EXEC_FILE=$(mktemp)\n' + commands += 'trap \'rm -f $SPUG_EXEC_FILE\' EXIT\n' + self.already_init = True + env_command = self._make_env_command(environment) if env_command: new_command += f'{env_command}\n' new_command += command + new_command += f'\necho {self.eof} $?\n' b64_command = base64.standard_b64encode(new_command.encode()) - - commands = 'export SPUG_EXEC_FILE=$(mktemp)\n' commands += f'echo {b64_command.decode()} | base64 -di > $SPUG_EXEC_FILE\n' - commands += 'bash $SPUG_EXEC_FILE\n' + commands += 'source $SPUG_EXEC_FILE\n' return commands + def _decode(self, content): + try: + content = content.decode() + except UnicodeDecodeError: + content = content.decode(encoding='GBK', errors='ignore') + return content + def __enter__(self): self.get_client() transport = self.client.get_transport() diff --git a/spug_api/requirements.txt b/spug_api/requirements.txt index 8baeb0f..6381eb1 100644 --- a/spug_api/requirements.txt +++ b/spug_api/requirements.txt @@ -2,7 +2,7 @@ apscheduler==3.7.0 Django==2.2.* channels==2.3.1 channels_redis==2.4.1 -paramiko==2.7.2 +paramiko==2.8.0 django-redis==4.10.0 requests==2.22.0 GitPython==3.0.8