blob: 4cc1f9653231283d99993ec709972b3bb37f9dd7 [file] [log] [blame]
Alexey Ivanovcc01a9c2019-01-16 09:50:46 -08001#!/usr/bin/python
Brendan Greggaa879972016-01-28 22:43:37 -08002#
3# bashreadline Print entered bash commands from all running shells.
4# For Linux, uses BCC, eBPF. Embedded C.
5#
JayceCaob26e26b2019-02-18 14:55:12 +08006# USAGE: bashreadline [-s SHARED]
Brendan Greggaa879972016-01-28 22:43:37 -08007# This works by tracing the readline() function using a uretprobe (uprobes).
JayceCaob26e26b2019-02-18 14:55:12 +08008# When you failed to run the script directly with error:
9# `Exception: could not determine address of symbol b'readline'`,
10# you may need specify the location of libreadline.so library
11# with `-s` option.
Brendan Greggaa879972016-01-28 22:43:37 -080012#
13# Copyright 2016 Netflix, Inc.
14# Licensed under the Apache License, Version 2.0 (the "License")
15#
16# 28-Jan-2016 Brendan Gregg Created this.
mcaleavyaee5f8232016-02-12 20:06:38 +000017# 12-Feb-2016 Allan McAleavy migrated to BPF_PERF_OUTPUT
Brendan Greggaa879972016-01-28 22:43:37 -080018
19from __future__ import print_function
20from bcc import BPF
21from time import strftime
JayceCaob26e26b2019-02-18 14:55:12 +080022import argparse
23
24parser = argparse.ArgumentParser(
25 description="Print entered bash commands from all running shells",
26 formatter_class=argparse.RawDescriptionHelpFormatter)
27parser.add_argument("-s", "--shared", nargs="?",
28 const="/lib/libreadline.so", type=str,
29 help="specify the location of libreadline.so library.\
30 Default is /lib/libreadline.so")
31args = parser.parse_args()
32
33name = args.shared if args.shared else "/bin/bash"
Brendan Greggaa879972016-01-28 22:43:37 -080034
35# load BPF program
36bpf_text = """
37#include <uapi/linux/ptrace.h>
mcaleavyaee5f8232016-02-12 20:06:38 +000038
39struct str_t {
40 u64 pid;
41 char str[80];
42};
43
44BPF_PERF_OUTPUT(events);
45
Brendan Greggaa879972016-01-28 22:43:37 -080046int printret(struct pt_regs *ctx) {
mcaleavyaee5f8232016-02-12 20:06:38 +000047 struct str_t data = {};
48 u32 pid;
Naveen N. Rao4afa96a2016-05-03 14:54:21 +053049 if (!PT_REGS_RC(ctx))
Brendan Greggaa879972016-01-28 22:43:37 -080050 return 0;
mcaleavyaee5f8232016-02-12 20:06:38 +000051 pid = bpf_get_current_pid_tgid();
52 data.pid = pid;
Naveen N. Rao4afa96a2016-05-03 14:54:21 +053053 bpf_probe_read(&data.str, sizeof(data.str), (void *)PT_REGS_RC(ctx));
mcaleavyaee5f8232016-02-12 20:06:38 +000054 events.perf_submit(ctx,&data,sizeof(data));
Brendan Greggaa879972016-01-28 22:43:37 -080055
56 return 0;
57};
58"""
mcaleavyaee5f8232016-02-12 20:06:38 +000059
Brendan Greggaa879972016-01-28 22:43:37 -080060b = BPF(text=bpf_text)
JayceCaob26e26b2019-02-18 14:55:12 +080061b.attach_uretprobe(name=name, sym="readline", fn_name="printret")
Brendan Greggaa879972016-01-28 22:43:37 -080062
63# header
64print("%-9s %-6s %s" % ("TIME", "PID", "COMMAND"))
65
mcaleavyaee5f8232016-02-12 20:06:38 +000066def print_event(cpu, data, size):
Xiaozhou Liu51d62d32019-02-15 13:03:05 +080067 event = b["events"].event(data)
Paul Chaignonae0e0252017-10-07 11:52:30 +020068 print("%-9s %-6d %s" % (strftime("%H:%M:%S"), event.pid,
jeromemarchandb96ebcd2018-10-10 01:58:15 +020069 event.str.decode('utf-8', 'replace')))
mcaleavyaee5f8232016-02-12 20:06:38 +000070
71b["events"].open_perf_buffer(print_event)
Brendan Greggaa879972016-01-28 22:43:37 -080072while 1:
Jerome Marchand51671272018-12-19 01:57:24 +010073 try:
74 b.perf_buffer_poll()
75 except KeyboardInterrupt:
76 exit()