A 新增终止任务执行功能

4.0
vapao 2022-10-08 15:33:55 +08:00
parent 35506a5690
commit 9fc7571422
4 changed files with 35 additions and 9 deletions

View File

@ -16,13 +16,13 @@ def exec_worker_handler(job):
class Job: class Job:
def __init__(self, key, name, hostname, port, username, pkey, command, interpreter, params=None, token=None, def __init__(self, token, key, name, hostname, port, username, pkey, command, interpreter, params=None, term=None):
term=None):
self.ssh = SSH(hostname, port, username, pkey, term=term) self.ssh = SSH(hostname, port, username, pkey, term=term)
self.key = key self.key = key
self.command = self._handle_command(command, interpreter) self.command = self._handle_command(command, interpreter)
self.token = token self.token = token
self.rds = get_redis_connection() self.rds = get_redis_connection()
self.rds_key = f'PID:{self.token}:{self.key}'
self.env = dict( self.env = dict(
SPUG_HOST_ID=str(self.key), SPUG_HOST_ID=str(self.key),
SPUG_HOST_NAME=name, SPUG_HOST_NAME=name,
@ -50,14 +50,12 @@ class Job:
self._send({'key': self.key, 'status': code}) self._send({'key': self.key, 'status': code})
def run(self): def run(self):
if not self.token:
with self.ssh:
return self.ssh.exec_command(self.command, self.env)
flag = time.time() flag = time.time()
self.send('\r\n\x1b[36m### Executing ...\x1b[0m\r\n') self.send('\r\n\x1b[36m### Executing ...\x1b[0m\r\n')
code = -1 code = -1
try: try:
with self.ssh: with self.ssh:
self.rds.set(self.rds_key, self.ssh.get_pid(), 7200)
for code, out in self.ssh.exec_command_with_stream(self.command, self.env): for code, out in self.ssh.exec_command_with_stream(self.command, self.env):
self.send(out) self.send(out)
human_time = human_seconds_time(time.time() - flag) human_time = human_seconds_time(time.time() - flag)
@ -70,4 +68,5 @@ class Job:
self.send(f'\r\n\x1b[31m### Exception {e}\x1b[0m') self.send(f'\r\n\x1b[31m### Exception {e}\x1b[0m')
raise e raise e
finally: finally:
self.rds.delete(self.rds_key)
self.send_status(code) self.send_status(code)

View File

@ -3,11 +3,12 @@
# Released under the AGPL-3.0 License. # Released under the AGPL-3.0 License.
from django.conf.urls import url from django.conf.urls import url
from apps.exec.views import * from apps.exec.views import TemplateView, TaskView, handle_terminate
from apps.exec.transfer import TransferView from apps.exec.transfer import TransferView
urlpatterns = [ urlpatterns = [
url(r'template/$', TemplateView.as_view()), url(r'template/$', TemplateView.as_view()),
url(r'do/$', TaskView.as_view()), url(r'do/$', TaskView.as_view()),
url(r'transfer/$', TransferView.as_view()), url(r'transfer/$', TransferView.as_view()),
url(r'terminate/$', handle_terminate),
] ]

View File

@ -120,4 +120,19 @@ class TaskView(View):
return json_response(error=error) return json_response(error=error)
@auth('exec.task.do')
def handle_terminate(request):
form, error = JsonParser(
Argument('token', help='参数错误'),
Argument('host_id', type=int, help='参数错误')
).parse(request.body)
if error is None:
host = Host.objects.get(pk=form.host_id)
rds = get_redis_connection()
rds_key = f'PID:{form.token}:{host.id}'
pid = rds.get(rds_key)
if pid:
with host.get_ssh() as ssh:
ssh.exec_command_raw(f'kill -9 {pid.decode()}')
rds.delete(rds_key)
return json_response(error=error)

View File

@ -58,6 +58,7 @@ class SSH:
self.sftp = None self.sftp = None
self.exec_file = None self.exec_file = None
self.term = term or {} self.term = term or {}
self.pid = None
self.eof = 'Spug EOF 2108111926' self.eof = 'Spug EOF 2108111926'
self.default_env = default_env self.default_env = default_env
self.regex = re.compile(r'Spug EOF 2108111926 (-?\d+)[\r\n]?') self.regex = re.compile(r'Spug EOF 2108111926 (-?\d+)[\r\n]?')
@ -174,6 +175,12 @@ class SSH:
sftp = self._get_sftp() sftp = self._get_sftp()
sftp.remove(path) sftp.remove(path)
def get_pid(self):
if self.pid:
return self.pid
self._get_channel()
return self.pid
def _get_channel(self): def _get_channel(self):
if self.channel: if self.channel:
return self.channel return self.channel
@ -183,13 +190,17 @@ class SSH:
command = '[ -n "$BASH_VERSION" ] && set +o history\n' command = '[ -n "$BASH_VERSION" ] && set +o history\n'
command += '[ -n "$ZSH_VERSION" ] && set +o zle && set -o no_nomatch\n' command += '[ -n "$ZSH_VERSION" ] && set +o zle && set -o no_nomatch\n'
command += 'export PS1= && stty -echo\n' command += 'export PS1= && stty -echo\n'
command = self._handle_command(command, self.default_env) command += f'echo {self.eof} $$\n'
self.channel.sendall(command) self.channel.sendall(command)
out = '' out = ''
while True: while True:
if self.channel.recv_ready(): if self.channel.recv_ready():
out += self._decode(self.channel.recv(8196)) out += self._decode(self.channel.recv(8196))
if self.regex.search(out): match = self.regex.search(out)
if match:
self.pid = int(match.group(1))
if self.pid <= 1:
raise Exception('Failed to get process pid')
self.stdout = self.channel.makefile('r') self.stdout = self.channel.makefile('r')
break break
elif counter >= 100: elif counter >= 100: