Last active
November 11, 2021 00:06
-
-
Save philpennock/6f6de681305ad65612d0809e29eef54f to your computer and use it in GitHub Desktop.
ps_byjail: ps(1) wrapper for FreeBSD, showing which jail each process is in
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
use strict; | |
use warnings; | |
#ps axdro user,pid,ppid,pgid,jid,stat,time,%cpu,%mem,vsz,rss,command :: | |
# $F[2] is PPID | |
# 0 means in-kernel process, all "real" processes (except init) have a positive integer as PPID | |
# Skip those where parent is this script | |
# $F[1] is PID | |
# Skip this script | |
# | |
# with 'j' flags were in $F[6] but we're putting them in $F[5] | |
# $F[5] has flags, which include 'J' for in-jail processes | |
# ax for all processes | |
# d for hierarchy, combined with r for sort-by-CPU between siblings | |
# o to control fields | |
my $PS = 'ps axdr'; | |
my $PS_o = 'user,pid,ppid,pgid,jid,stat,time,%cpu,%mem,vsz,rss,command'; | |
my $byj = {}; | |
my @hdrs = (); | |
my $jnames = { 0 => "<nojail>" }; | |
my %ps_takes_param = map {; "-$_" => 1 } qw/O o G J M N p t U/; | |
my %ps_inhibit_PS_o = map {; "-$_" => 1 } qw/O o/; | |
# if argv lists jail numbers/ids, restrict to those; signal not restricting | |
# by leaving this undef (below is set undef if empty after parsing argv): | |
my $only_jails = {}; | |
my ($COL_pid, $COL_ppid, $COL_jid, $COL_stat); | |
my %COL_set = ( | |
'pid' => \$COL_pid, | |
'ppid' => \$COL_ppid, | |
'jid' => \$COL_jid, | |
'stat' => \$COL_stat, | |
); | |
sub extract_ps_fields { | |
my $opt = $_[1]; | |
my @f = split /(?:\s|,)/, $_[0]; | |
@f = ('pid', @f, qw/tt stat time command/) if $opt eq '-O'; | |
for (my $i = 0; $i < $#f; $i++) { | |
my $o = lc ((split /=/, $f[$i])[0]); | |
if (exists $COL_set{$o}) { | |
${$COL_set{$o}} = $i; | |
#print "DBG: $o ${$COL_set{$o}}\n"; | |
} | |
} | |
my $bad = 0; | |
foreach my $k (sort keys %COL_set) { | |
next if defined ${$COL_set{$k}}; | |
print STDERR "Missing: ps field '$k'\n"; | |
$bad = 1; | |
} | |
exit 1 if $bad; | |
} | |
my $swallow = undef; | |
my $want_PS_o = 1; | |
foreach my $i (@ARGV) { | |
# full parsing would handle -abcXfoo where -X takes foo, we assume caller | |
# is splitting things differently | |
if (defined $swallow) { | |
extract_ps_fields($i, $swallow) if exists $ps_inhibit_PS_o{$swallow}; | |
$swallow = undef; | |
$PS .= " $i"; | |
next; | |
} | |
if ($i =~ /^-/) { | |
$PS .= " $i"; | |
$swallow = $i if exists $ps_takes_param{$i}; | |
$want_PS_o = 0 if exists $ps_inhibit_PS_o{$i}; | |
next; | |
} | |
#print "DBG: only-jails: $i\n"; | |
$only_jails->{$i} = 1; | |
$only_jails->{0} = 1 if lc($i) eq 'nojail'; | |
} | |
if ($want_PS_o) { | |
$PS .= " -o $PS_o"; | |
extract_ps_fields($PS_o, "-o"); | |
} | |
#print "DBG: PS: $PS\n"; | |
$only_jails = undef unless scalar %{$only_jails}; | |
foreach (`jls -n`) { | |
/\bjid=(\S++).*\bname=(\S++)/ or next; | |
$jnames->{$1} = $2; | |
#print "DBG: <$1> <$2>\n" unless defined $only_jails; | |
} | |
foreach (`$PS`) { | |
my @F = split(' '); | |
if ($F[$COL_pid] eq "PID") { push @hdrs, $_; next }; | |
next if $F[$COL_ppid] eq "0" && $F[$COL_pid] ne "1"; | |
next if $F[$COL_pid] eq $$ or $F[$COL_ppid] eq $$; | |
#print "DBG: new jid: $F[$COL_jid]\n" unless exists $byj->{$F[$COL_jid]}; | |
$byj->{$F[$COL_jid]} = [] unless exists $byj->{$F[$COL_jid]}; | |
push @{$byj->{$F[$COL_jid]}}, $_; | |
} | |
#print "DBG: jail: $_\n" foreach sort keys %$byj; | |
map { s/^(.+)$/\e[33m$1\e[0m/ } @hdrs; # make headers yellow | |
foreach my $j (sort {$a <=> $b} keys %$byj) { | |
if (defined $only_jails) { | |
next unless exists $only_jails->{$j} or exists $only_jails->{$jnames->{$j}}; | |
}; | |
print "\e[32mJail: \e[1m$j\t$jnames->{$j}\e[0m\n"; | |
print foreach @hdrs; | |
print foreach @{$byj->{$j}}; | |
print "\n"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment