1#!/usr/bin/env bcc-lua 2--[[ 3Copyright 2016 Marek Vavrusa <mvavrusa@cloudflare.com> 4 5Licensed under the Apache License, Version 2.0 (the "License"); 6you may not use this file except in compliance with the License. 7You may obtain a copy of the License at 8 9http://www.apache.org/licenses/LICENSE-2.0 10 11Unless required by applicable law or agreed to in writing, software 12distributed under the License is distributed on an "AS IS" BASIS, 13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14See the License for the specific language governing permissions and 15limitations under the License. 16]] 17-- Trace readline() call from all bash instances (print bash commands from all running shells). 18-- This is rough equivallent to `bashreadline` with output through perf event API. 19-- Source: http://www.brendangregg.com/blog/2016-02-08/linux-ebpf-bcc-uprobes.html 20local ffi = require('ffi') 21local bpf = require('bpf') 22local S = require('syscall') 23-- Perf event map 24local sample_t = 'struct { uint64_t pid; char str[80]; }' 25local events = bpf.map('perf_event_array') 26-- Kernel-space part of the program 27local probe = bpf.uprobe('/bin/bash:readline', function (ptregs) 28 local sample = ffi.new(sample_t) 29 sample.pid = pid_tgid() 30 ffi.copy(sample.str, ffi.cast('char *', ptregs.ax)) -- Cast `ax` to string pointer and copy to buffer 31 perf_submit(events, sample) -- Write buffer to perf event map 32end, true, -1, 0) 33-- User-space part of the program 34local log = events:reader(nil, 0, sample_t) -- Must specify PID or CPU_ID to observe 35print(' TASK-PID TIMESTAMP FUNCTION') 36print(' | | | |') 37while true do 38 log:block() -- Wait until event reader is readable 39 for _,e in log:read() do -- Collect available reader events 40 print(string.format('%12s%-16s %-10s %s', '', tonumber(e.pid), os.date("%H:%M:%S"), ffi.string(e.str))) 41 end 42end 43