blob: 3e1899769a6666cec62697dc91574c75abf21221 [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>
Juergen Hoetzel4995db02019-06-07 20:58:58 +020038#include <linux/sched.h>
mcaleavyaee5f8232016-02-12 20:06:38 +000039
40struct str_t {
41 u64 pid;
42 char str[80];
43};
44
45BPF_PERF_OUTPUT(events);
46
Brendan Greggaa879972016-01-28 22:43:37 -080047int printret(struct pt_regs *ctx) {
mcaleavyaee5f8232016-02-12 20:06:38 +000048 struct str_t data = {};
Juergen Hoetzel4995db02019-06-07 20:58:58 +020049 char comm[TASK_COMM_LEN] = {};
mcaleavyaee5f8232016-02-12 20:06:38 +000050 u32 pid;
Naveen N. Rao4afa96a2016-05-03 14:54:21 +053051 if (!PT_REGS_RC(ctx))
Brendan Greggaa879972016-01-28 22:43:37 -080052 return 0;
Hengqi Chenf0a0dc72021-05-20 22:49:25 +080053 pid = bpf_get_current_pid_tgid() >> 32;
mcaleavyaee5f8232016-02-12 20:06:38 +000054 data.pid = pid;
Sumanth Korikkar023154c2020-04-20 05:54:57 -050055 bpf_probe_read_user(&data.str, sizeof(data.str), (void *)PT_REGS_RC(ctx));
Juergen Hoetzel4995db02019-06-07 20:58:58 +020056
57 bpf_get_current_comm(&comm, sizeof(comm));
58 if (comm[0] == 'b' && comm[1] == 'a' && comm[2] == 's' && comm[3] == 'h' && comm[4] == 0 ) {
59 events.perf_submit(ctx,&data,sizeof(data));
60 }
61
Brendan Greggaa879972016-01-28 22:43:37 -080062
63 return 0;
64};
65"""
mcaleavyaee5f8232016-02-12 20:06:38 +000066
Brendan Greggaa879972016-01-28 22:43:37 -080067b = BPF(text=bpf_text)
JayceCaob26e26b2019-02-18 14:55:12 +080068b.attach_uretprobe(name=name, sym="readline", fn_name="printret")
Brendan Greggaa879972016-01-28 22:43:37 -080069
70# header
xingfeng251003e49482022-03-17 13:07:16 +080071print("%-9s %-7s %s" % ("TIME", "PID", "COMMAND"))
Brendan Greggaa879972016-01-28 22:43:37 -080072
mcaleavyaee5f8232016-02-12 20:06:38 +000073def print_event(cpu, data, size):
Xiaozhou Liu51d62d32019-02-15 13:03:05 +080074 event = b["events"].event(data)
xingfeng251003e49482022-03-17 13:07:16 +080075 print("%-9s %-7d %s" % (strftime("%H:%M:%S"), event.pid,
jeromemarchandb96ebcd2018-10-10 01:58:15 +020076 event.str.decode('utf-8', 'replace')))
mcaleavyaee5f8232016-02-12 20:06:38 +000077
78b["events"].open_perf_buffer(print_event)
Brendan Greggaa879972016-01-28 22:43:37 -080079while 1:
Jerome Marchand51671272018-12-19 01:57:24 +010080 try:
81 b.perf_buffer_poll()
82 except KeyboardInterrupt:
83 exit()