예제 #1
0
파일: cli.py 프로젝트: kentyu06/punch-q
def save(queue, limit, directory):
    """
        Save messages from a queue to a file, non-destructively.
    """

    mqstate.validate(['host', 'port', 'channel'])

    # Automatically generate a directory to save messages to
    if not directory:
        directory = safe_filename(mqstate.host + '_' + safe_filename(queue))
        click.secho(f'Saving messages to \'{directory}\'...', dim=True, fg='green')

    # check that the directory is ready for use
    absolute_path = os.path.abspath(directory)
    if not os.path.exists(absolute_path):
        click.secho(f'Creating {absolute_path} to save messages in...', dim=True)
        os.makedirs(absolute_path, mode=0o755)

    click.secho(f'Saving a maximum of {limit} messages from {queue}...', dim=True)

    qmgr = pymqi.connect(mqstate.qm_name, mqstate.channel, mqstate.get_host(),
                         mqstate.username, mqstate.password)

    # https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.5.0/com.ibm.mq.ref.dev.doc/q096780_.htm
    # https://github.com/dsuch/pymqi/blob/master/code/examples/put_get_correl_id.py
    gmo = pymqi.GMO()
    gmo.Options = pymqi.CMQC.MQGMO_BROWSE_NEXT
    queue = pymqi.Queue(qmgr, str(queue), pymqi.CMQC.MQOO_BROWSE)

    message_count = 0

    while message_count < limit:
        try:

            request_md = pymqi.MD()
            message = queue.get(None, request_md, gmo)

            file_name = filename_from_attributes(
                mq_string(request_md.PutDate),
                mq_string(request_md.PutTime),
                '.' + hashlib.sha1(request_md.MsgId).hexdigest() + '.',
                request_md.MsgType,
                request_md.Expiry,
                mq_string(request_md.UserIdentifier),
                mq_string(request_md.Format),
                mq_string(request_md.PutApplName))

            # try get a safe filename from all of that
            file_name = slugify(file_name)

            with open(os.path.join(absolute_path, file_name), 'wb') as f:
                f.write(message)

            click.secho(f'{message_count}: Wrote message to {file_name}', bold=True, fg='green')

        except pymqi.MQMIError as dme:
            if dme.comp == pymqi.CMQC.MQCC_FAILED and dme.reason == pymqi.CMQC.MQRC_NO_MSG_AVAILABLE:
                click.secho('Dump complete. No more messages on the queue.', fg='yellow')

                break

            # if we are not allowed to GET on this queue, mention that and quit
            if dme.comp == pymqi.CMQ.MQCC_FAILED and dme.reason == pymqi.CMQC.MQRC_GET_INHIBITED:
                click.secho('GET not allowed on queue with current access.', fg='red')

                break

            else:
                raise dme

        message_count += 1

    click.secho(f'Saved {message_count} message(s) in total.', bold=True)

    queue.close()
    qmgr.disconnect()
예제 #2
0
파일: cli.py 프로젝트: kentyu06/punch-q
def sniff(queue, store, directory):
    """
        Sniff messages on a queue, non-destructively.

        Sniffs queues messages on a queue by opening the
        queue in a read only mode. Incoming messages will
        be dumped to the screen by default. If the --store
        flag is specified, messages will also be written
        to disk as they arrive.
    """

    mqstate.validate(['host', 'port'])

    # check if a directory was set but store was not
    if directory and not store:
        click.secho('A directory was set to store messages but --store flag was not provided, ignoring...',
                    bold=True, fg='yellow')

    # Prepare the destination directory if messages should also be saved
    if store:
        # Automatically generate a directory to save messages to
        if not directory:
            directory = safe_filename(mqstate.host + '_' + safe_filename(queue))
            click.secho(f'Messages will be saved to directory \'{directory}\'', dim=True, fg='green')

        # check that the directory is ready for use
        absolute_path = os.path.abspath(directory)
        if not os.path.exists(absolute_path):
            click.secho(f'Creating {absolute_path} to save messages in...', dim=True)
            os.makedirs(absolute_path, mode=0o755)

    qmgr = pymqi.connect(mqstate.qm_name, mqstate.channel, mqstate.get_host(),
                         mqstate.username, mqstate.password)

    # https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.5.0/com.ibm.mq.ref.dev.doc/q096780_.htm
    # https://github.com/dsuch/pymqi/blob/master/code/examples/put_get_correl_id.py
    # https://github.com/dsuch/pymqi/blob/master/code/examples/get_wait_multiple_messages.py
    gmo = pymqi.GMO()
    gmo.Options = pymqi.CMQC.MQGMO_BROWSE_NEXT | pymqi.CMQC.MQGMO_WAIT | pymqi.CMQC.MQGMO_FAIL_IF_QUIESCING
    gmo.WaitInterval = 2 * 1000  # 5 seconds

    queue = pymqi.Queue(qmgr, str(queue), pymqi.CMQC.MQOO_BROWSE)
    request_md = pymqi.MD()

    # simple counter for statistics
    message_count = 0
    click.secho('Waiting for messages to arrive...', dim=True)

    while True:
        try:
            # grab the message
            message = queue.get(None, request_md, gmo)
            message_count += 1

            # Save the message if we need to we do this early as
            # messages could be reformatted to be printed to screen.
            if store:
                file_name = filename_from_attributes(
                    mq_string(request_md.PutDate),
                    mq_string(request_md.PutTime),
                    '.' + hashlib.sha1(request_md.MsgId).hexdigest() + '.',
                    request_md.MsgType,
                    request_md.Expiry,
                    mq_string(request_md.UserIdentifier),
                    mq_string(request_md.Format),
                    mq_string(request_md.PutApplName))

                # try get a safe filename from all of that
                file_name = slugify(file_name)

                with open(os.path.join(absolute_path, file_name), 'wb') as f:
                    f.write(message)

                click.secho(f'{message_count}: Wrote message to {file_name}', bold=True, fg='green')

            # check if we have a MQSTR message. If we don't, try and filter
            # non-printables.
            if request_md.Format.strip() not in ['MQSTR', '']:
                # remove non-printables and update the Format
                # column with (stripped) so that it is visible
                message = message.decode('ascii', errors='ignore')
                request_md.Format = mq_string(request_md.Format) + ' (stripped)'

            click.secho(f'Message #{message_count}', fg='green')

            table = get_table_handle([
                'Date', 'Time', 'MsgID', 'MsgType', 'Expiry', 'User', 'Format', 'App Name'], markdown=False)

            table.append_row([
                mq_string(request_md.PutDate),
                mq_string(request_md.PutTime),
                request_md.MsgId.decode('ascii', errors='ignore'),
                request_md.MsgType,
                request_md.Expiry,
                mq_string(request_md.UserIdentifier),
                mq_string(request_md.Format),
                mq_string(request_md.PutApplName),
            ])

            # Print a 'header' for the message
            click.secho(table.get_string())

            # Print the message itself
            click.secho('' + '*' * 40 + ' BEGIN MESSAGE DATA ' + '*' * 40, dim=True)
            click.secho(message, bold=True)
            click.secho('*' * 41 + ' END MESSAGE DATA ' + '*' * 41 + '\n', dim=True)

            # reset the request descriptor so we can reuse it for the next message.
            request_md.MsgId = pymqi.CMQC.MQMI_NONE
            request_md.CorrelId = pymqi.CMQC.MQCI_NONE
            request_md.GroupId = pymqi.CMQC.MQGI_NONE
            request_md.Format = pymqi.CMQC.MQGI_NONE

        except pymqi.MQMIError as dme:

            # No messages, that's OK, we can ignore it.
            if dme.comp == pymqi.CMQC.MQCC_FAILED and dme.reason == pymqi.CMQC.MQRC_NO_MSG_AVAILABLE:
                continue

            # if we are not allowed to GET on this queue, mention that and quit
            if dme.comp == pymqi.CMQ.MQCC_FAILED and dme.reason == pymqi.CMQC.MQRC_GET_INHIBITED:
                click.secho('GET not allowed on queue with current credentials.', fg='red')

                break

            else:
                # Some other error condition.
                raise dme

        except KeyboardInterrupt as _:
            click.secho('Stopping...', fg='yellow')
            break

    click.secho(f'\nSniffed {message_count} message(s) in total.', dim=True)

    queue.close()
    qmgr.disconnect()