예제 #1
0
def posix_shell(chan,
                channel,
                log_name=None,
                width=90,
                height=40,
                elementid=None):
    from webterminal.asgi import channel_layer
    stdout = list()
    begin_time = time.time()
    last_write_time = {'last_activity_time': begin_time}
    command = list()
    if elementid:
        logobj = Log.objects.get(channel=elementid)
    else:
        logobj = Log.objects.get(channel=channel)
    vim_flag = False
    vim_data = ''
    try:
        chan.settimeout(0.0)
        while True:
            try:
                x = u(chan.recv(1024))
                if len(x) == 0:
                    if elementid:
                        channel_layer.send(
                            channel, {
                                'text':
                                json.dumps([
                                    'disconnect',
                                    smart_unicode('\r\n*** EOF\r\n'),
                                    elementid.rsplit('_')[0]
                                ])
                            })
                    else:
                        channel_layer.send(
                            channel, {
                                'text':
                                json.dumps([
                                    'disconnect',
                                    smart_unicode('\r\n*** EOF\r\n')
                                ])
                            })
                    break
                now = time.time()
                delay = now - last_write_time['last_activity_time']
                last_write_time['last_activity_time'] = now
                if x == "exit\r\n" or x == "logout\r\n" or x == 'logout':
                    chan.close()
                else:
                    if vim_flag:
                        vim_data += x
                    logger.debug('raw data {0}'.format(command))
                    if '\r\n' not in x:
                        command.append(x)
                    else:
                        command = CommandDeal().deal_command(''.join(command))
                        if len(command) != 0:
                            #vim command record patch
                            logger.debug('command {0}'.format(command))
                            if command.strip().startswith(
                                    'vi') or command.strip().startswith('fg'):
                                CommandLog.objects.create(log=logobj,
                                                          command=command)
                                vim_flag = True
                            else:
                                if vim_flag:
                                    if re.compile('\[.*@.*\][\$#]').search(
                                            vim_data):
                                        vim_flag = False
                                        vim_data = ''
                                else:
                                    CommandLog.objects.create(log=logobj,
                                                              command=command)
                        command = list()

                    if isinstance(x, unicode):
                        stdout.append([delay, x])
                    else:
                        stdout.append([
                            delay,
                            codecs.getincrementaldecoder('UTF-8')(
                                'replace').decode(x)
                        ])
                if isinstance(x, unicode):
                    if elementid:
                        channel_layer.send(
                            channel, {
                                'text':
                                json.dumps(
                                    ['stdout', x,
                                     elementid.rsplit('_')[0]])
                            })
                    else:
                        channel_layer.send(channel,
                                           {'text': json.dumps(['stdout', x])})
                else:
                    if elementid:
                        channel_layer.send(
                            channel, {
                                'text':
                                json.dumps([
                                    'stdout',
                                    smart_unicode(x),
                                    elementid.rsplit('_')[0]
                                ])
                            })
                    else:
                        channel_layer.send(
                            channel,
                            {'text': json.dumps(['stdout',
                                                 smart_unicode(x)])})
                #send message to monitor group
                if log_name:
                    channel_layer.send_group(
                        u'monitor-{0}'.format(log_name.rsplit('/')[1]),
                        {'text': json.dumps(['stdout',
                                             smart_unicode(x)])})
            except socket.timeout:
                pass
            except Exception, e:
                logger.error(traceback.print_exc())
                if elementid:
                    channel_layer.send(
                        channel, {
                            'text':
                            json.dumps([
                                'stdout',
                                'A bug find,You can report it to me' +
                                smart_unicode(e),
                                elementid.rsplit('_')[0]
                            ])
                        })
                else:
                    channel_layer.send(
                        channel, {
                            'text':
                            json.dumps([
                                'stdout',
                                'A bug find,You can report it to me' +
                                smart_unicode(e)
                            ])
                        })

    finally:
        attrs = {
            "version":
            1,
            "width":
            width,  #int(subprocess.check_output(['tput', 'cols'])),
            "height":
            height,  #int(subprocess.check_output(['tput', 'lines'])),
            "duration":
            round(time.time() - begin_time, 6),
            "command":
            os.environ.get('SHELL', None),
            'title':
            None,
            "env": {
                "TERM": os.environ.get('TERM'),
                "SHELL": os.environ.get('SHELL', 'sh')
            },
            'stdout':
            list(map(lambda frame: [round(frame[0], 6), frame[1]], stdout))
        }
        mkdir_p('/'.join(os.path.join(MEDIA_ROOT, log_name).rsplit('/')[0:-1]))
        with open(os.path.join(MEDIA_ROOT, log_name), "a") as f:
            f.write(
                json.dumps(attrs,
                           ensure_ascii=True,
                           cls=CustomeFloatEncoder,
                           indent=2))

        if elementid:
            audit_log = Log.objects.get(channel=elementid,
                                        log=log_name.rsplit('/')[-1])
        else:
            audit_log = Log.objects.get(channel=channel,
                                        log=log_name.rsplit('/')[-1])
        audit_log.is_finished = True
        audit_log.end_time = timezone.now()
        audit_log.save()
        #hand ssh terminal exit
        queue = get_redis_instance()
        redis_channel = queue.pubsub()
        queue.publish(channel, json.dumps(['close']))
예제 #2
0
def posix_shell(chan, channel, channelid):

    stdout = list()
    begin_time = time.time()
    last_write_time = {'last_activity_time': begin_time}
    command = list()
    logobj = Log.objects.get(log=channelid)
    vim_flag = False
    vim_data = ''

    try:
        directory_date_time = timezone.now()
        log_name = os.path.join(
            '{0}-{1}-{2}'.format(directory_date_time.year,
                                 directory_date_time.month,
                                 directory_date_time.day),
            '{0}'.format(channelid))
        from webterminal.asgi import channel_layer
        # terminate ssh session control
        redis_instance = get_redis_instance()
        redis_sub = redis_instance.pubsub()
        redis_sub.subscribe(logobj.channel)
        while True:

            text = redis_sub.get_message()
            if text:
                try:
                    if isinstance(text['data'], bytes):
                        text['data'] = smart_unicode(text['data'])
                    data = json.loads(text['data'])
                except:
                    data = []
                if len(data) >= 1 and str(data[0]) == 'close':
                    if not channel.closed:
                        channel.close()

            r, w, x = select.select([channel], [], [])
            if channel in r:
                data = channel.recv(1024 * 24)
                if len(data) == 0:
                    if not channel.closed:
                        channel.send('\r\n*** EOF\r\n')
                    break
                if data == "exit\r\n" or data == "logout\r\n" or data == 'logout':
                    channel.close()

                now = time.time()
                delay = now - last_write_time['last_activity_time']
                last_write_time['last_activity_time'] = now

                if vim_flag:
                    vim_data += data

                if '\r' not in smart_unicode(data):
                    command.append(smart_unicode(data))
                else:
                    command_result = CommandDeal().deal_command(
                        ''.join(command))
                    if len(command_result) != 0:
                        # vim command record patch
                        if command_result.strip().startswith(
                                'vi') or command_result.strip().startswith(
                                    'fg'):
                            CommandLog.objects.create(
                                log=logobj, command=command_result[0:255])
                            vim_flag = True
                        else:
                            if vim_flag:
                                if re.compile('\[.*@.*\][\$#]').search(
                                        vim_data):
                                    vim_flag = False
                                    vim_data = ''
                            else:
                                CommandLog.objects.create(
                                    log=logobj, command=command_result[0:255])
                    command = list()

                if isinstance(data, unicode):
                    stdout.append([delay, data])
                else:
                    stdout.append([
                        delay,
                        codecs.getincrementaldecoder('UTF-8')(
                            'replace').decode(data)
                    ])

                channel_layer.send_group(
                    smart_unicode('monitor-{0}'.format(channelid)),
                    {'text': json.dumps(['stdout',
                                         smart_unicode(data)])})
                if not chan.closed:
                    chan.send(data)
            else:
                print('else')
    finally:
        attrs = {
            "version":
            1,
            "width":
            180,
            "height":
            40,
            "duration":
            round(time.time() - begin_time, 6),
            "command":
            os.environ.get('SHELL', None),
            'title':
            None,
            "env": {
                "TERM": os.environ.get('TERM'),
                "SHELL": os.environ.get('SHELL', 'sh')
            },
            'stdout':
            list(map(lambda frame: [round(frame[0], 6), frame[1]], stdout))
        }
        mkdir_p('/'.join(os.path.join(MEDIA_ROOT, log_name).rsplit('/')[0:-1]))
        with open(os.path.join(MEDIA_ROOT, log_name), "a") as f:
            f.write(
                json.dumps(attrs,
                           ensure_ascii=True,
                           cls=CustomeFloatEncoder,
                           indent=2))

        logobj.is_finished = True
        logobj.end_time = timezone.now()
        logobj.save()

        chan.close()
        channel.close()
예제 #3
0
def posix_shell(chan,channel,log_name=None,width=90,height=40):
    from webterminal.asgi import channel_layer
    stdout = list()
    begin_time = time.time()
    last_write_time = {'last_activity_time':begin_time}    
    try:
        chan.settimeout(0.0)
        while True:
            try:               
                x = u(chan.recv(1024))
                if len(x) == 0:
                    channel_layer.send(channel, {'text': json.dumps(['disconnect',smart_unicode('\r\n*** EOF\r\n')]) })
                    break             
                now = time.time()
                delay = now - last_write_time['last_activity_time']
                last_write_time['last_activity_time'] = now                
                if x == "exit\r\n" or x == "logout\r\n" or x == 'logout':
                    chan.close()
                else:
                    if isinstance(x,unicode):
                        stdout.append([delay,x])
                    else:
                        stdout.append([delay,codecs.getincrementaldecoder('UTF-8')('replace').decode(x)])
                if isinstance(x,unicode):
                    channel_layer.send(channel, {'text': json.dumps(['stdout',x]) })
                else:
                    channel_layer.send(channel, {'text': json.dumps(['stdout',smart_unicode(x)]) })
                #send message to monitor group
                if log_name:
                    channel_layer.send_group(u'monitor-{0}'.format(log_name.rsplit('/')[1].rsplit('.json')[0]), {'text': json.dumps(['stdout',smart_unicode(x)]) })
            except socket.timeout:
                pass
            except Exception,e:
                print traceback.print_exc()
                channel_layer.send(channel, {'text': json.dumps(['stdout','A bug find,You can report it to me' + smart_unicode(e)]) })

    finally:
        attrs = {
            "version": 1,
            "width": width,#int(subprocess.check_output(['tput', 'cols'])),
            "height": height,#int(subprocess.check_output(['tput', 'lines'])),
            "duration": round(time.time()- begin_time,6),
            "command": os.environ.get('SHELL',None),
            'title':None,
            "env": {
                "TERM": os.environ.get('TERM'),
                "SHELL": os.environ.get('SHELL','sh')
                },
            'stdout':list(map(lambda frame: [round(frame[0], 6), frame[1]], stdout))
            }
        mkdir_p('/'.join(os.path.join(MEDIA_ROOT,log_name).rsplit('/')[0:-1]))
        with open(os.path.join(MEDIA_ROOT,log_name), "a") as f:
            f.write(json.dumps(attrs, ensure_ascii=True,cls=CustomeFloatEncoder,indent=2))
        
        audit_log=SshLog.objects.get(channel=channel,log=log_name.rsplit('/')[-1].rsplit('.json')[0])
        audit_log.is_finished = True
        audit_log.end_time = timezone.now()
        audit_log.save()
        #hand ssh terminal exit
        queue = get_redis_instance()
        redis_channel = queue.pubsub()
        queue.publish(channel, json.dumps(['close']))