1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
#! /usr/bin/perl
# SPDX-FileCopyrightText: edef <edef@unfathomable.blue>
# SPDX-License-Identifier: OSL-3.0
use strict;
use POSIX qw(mkfifo);
@ARGV or die "Usage: $0 PROGRAM [ARG]... 2> [LOG FILE]";
die "bpftrace does not support spaces in argv" if grep {/ /} @ARGV;
unlink(my $fifo = "tracepipe");
mkfifo($fifo, 0600) or die;
my $script = do { local $/; <DATA> };
defined(my $pid = fork) or die;
if (!$pid) {
open(STDERR, ">&", STDOUT) or die;
exec(
'systemd-run', '--user', '--scope', '--',
# NOTE: this expects bpftrace to be SUID-root,
# and relies on shells dropping euid
'bpftrace', '-o', $fifo, '-e', $script, '-c',
join(' ', @ARGV)
) or die;
}
my %count;
# TODO(edef): if bpftrace fails, the FIFO will never open
open(TRACE, '<', $fifo) or die;
while (<TRACE>) {
chomp;
next if /^Attaching \d+ probes[.][.][.]$/ or /^$/;
/^@\[tracepoint:syscalls:sys_enter_(\w+), (.+)\]: (\d+)$/ or die $_;
$count{$1}{$2} += $3;
}
waitpid $pid, 0;
foreach my $comm (sort keys %count) {
die "unhandled: $comm" if $comm =~ /\s/;
my $comm_count = $count{$comm};
foreach my $sys (sort keys %$comm_count) {
my $n = $comm_count->{$sys};
print STDERR "$comm\t$sys\t$n\n";
}
}
__DATA__
BEGIN {
@cgroup = cgroup;
@self = pid;
}
tracepoint:syscalls:sys_enter_* /cgroup == @cgroup && pid != @self/ {
@[probe, comm] = count();
}
interval:s:1 {
print(@);
clear(@);
}
tracepoint:sched:sched_process_exit /tid == cpid/ {
clear(@cgroup);
clear(@self);
exit();
}
|