#!/usr/bin/python # # bashreadline Print entered bash commands from all running shells. # For Linux, uses BCC, eBPF. Embedded C. # # This works by tracing the readline() function using a uretprobe (uprobes). # # Copyright 2016 Netflix, Inc. # Licensed under the Apache License, Version 2.0 (the "License") # # 28-Jan-2016 Brendan Gregg Created this. # 12-Feb-2016 Allan McAleavy migrated to BPF_PERF_OUTPUT from __future__ import print_function from bcc import BPF from time import strftime import ctypes as ct # load BPF program bpf_text = """ #include <uapi/linux/ptrace.h> struct str_t { u64 pid; char str[80]; }; BPF_PERF_OUTPUT(events); int printret(struct pt_regs *ctx) { struct str_t data = {}; u32 pid; if (!PT_REGS_RC(ctx)) return 0; pid = bpf_get_current_pid_tgid(); data.pid = pid; bpf_probe_read(&data.str, sizeof(data.str), (void *)PT_REGS_RC(ctx)); events.perf_submit(ctx,&data,sizeof(data)); return 0; }; """ STR_DATA = 80 class Data(ct.Structure): _fields_ = [ ("pid", ct.c_ulonglong), ("str", ct.c_char * STR_DATA) ] b = BPF(text=bpf_text) b.attach_uretprobe(name="/bin/bash", sym="readline", fn_name="printret") # header print("%-9s %-6s %s" % ("TIME", "PID", "COMMAND")) def print_event(cpu, data, size): event = ct.cast(data, ct.POINTER(Data)).contents print("%-9s %-6d %s" % (strftime("%H:%M:%S"), event.pid, event.str.decode('utf-8', 'replace'))) b["events"].open_perf_buffer(print_event) while 1: b.perf_buffer_poll()