1#!/usr/bin/env python 2# 3# bashreadline Print entered bash commands from all running shells. 4# For Linux, uses BCC, eBPF. Embedded C. 5# 6# This works by tracing the readline() function using a uretprobe (uprobes). 7# 8# Copyright 2016 Netflix, Inc. 9# Licensed under the Apache License, Version 2.0 (the "License") 10# 11# 28-Jan-2016 Brendan Gregg Created this. 12# 12-Feb-2016 Allan McAleavy migrated to BPF_PERF_OUTPUT 13 14from __future__ import print_function 15from bcc import BPF 16from time import strftime 17import ctypes as ct 18 19# load BPF program 20bpf_text = """ 21#include <uapi/linux/ptrace.h> 22 23struct str_t { 24 u64 pid; 25 char str[80]; 26}; 27 28BPF_PERF_OUTPUT(events); 29 30int printret(struct pt_regs *ctx) { 31 struct str_t data = {}; 32 u32 pid; 33 if (!PT_REGS_RC(ctx)) 34 return 0; 35 pid = bpf_get_current_pid_tgid(); 36 data.pid = pid; 37 bpf_probe_read(&data.str, sizeof(data.str), (void *)PT_REGS_RC(ctx)); 38 events.perf_submit(ctx,&data,sizeof(data)); 39 40 return 0; 41}; 42""" 43STR_DATA = 80 44 45class Data(ct.Structure): 46 _fields_ = [ 47 ("pid", ct.c_ulonglong), 48 ("str", ct.c_char * STR_DATA) 49 ] 50 51b = BPF(text=bpf_text) 52b.attach_uretprobe(name="/bin/bash", sym="readline", fn_name="printret") 53 54# header 55print("%-9s %-6s %s" % ("TIME", "PID", "COMMAND")) 56 57def print_event(cpu, data, size): 58 event = ct.cast(data, ct.POINTER(Data)).contents 59 print("%-9s %-6d %s" % (strftime("%H:%M:%S"), event.pid, 60 event.str.decode('utf-8', 'replace'))) 61 62b["events"].open_perf_buffer(print_event) 63while 1: 64 try: 65 b.perf_buffer_poll() 66 except KeyboardInterrupt: 67 exit() 68