Compare commits
30 Commits
Author | SHA1 | Date |
---|---|---|
Zane C. B-H | e519e0d7c7 | |
Zane C. B-H | 0ffb462b0b | |
Zane C. B-H | 55cd2535e3 | |
Zane C. B-H | 438d9b7d78 | |
Zane C. B-H | 9ecc05fe34 | |
Zane C. B-H | 680b4cbe62 | |
Zane C. B-H | f3089ada01 | |
Zane C. B-H | adc7220396 | |
Zane C. B-H | 357d7e4dbe | |
Zane C. B-H | f8d90d9732 | |
Zane C. B-H | ae3b04a789 | |
Zane C. B-H | 529fe02f05 | |
Zane C. B-H | 37b53bf0d1 | |
Zane C. B-H | 84b13dba51 | |
Zane C. B-H | 703cd7c497 | |
Zane C. B-H | 5d7b6abc87 | |
Zane C. B-H | 50c0dd68c9 | |
Zane C. B-H | 85618c1cf0 | |
Zane C. B-H | 3c107240c0 | |
Zane C. B-H | 469676b3b4 | |
Zane C. B-H | 62d6c30622 | |
Zane C. B-H | b53a481038 | |
Zane C. B-H | c7d9ece486 | |
Zane C. B-H | 736c1e71ef | |
Zane C. B-H | 9c33541969 | |
Zane C. B-H | 4371e312ba | |
Zane C. B-H | bb355c9e2b | |
Zane C. B-H | ec3bbe7a08 | |
Zane C. B-H | c468f42c0b | |
Zane C. B-H | 3f3e09cfcf |
|
@ -1,5 +1,46 @@
|
|||
Revision history for Net-Connection-ncnetstat
|
||||
|
||||
0.8.0 2023-06-01/13:15
|
||||
- Don't try to sort by default now.
|
||||
|
||||
0.7.1 2021-02-19/08:00
|
||||
- Bump the min version of Text::ANSITable required to 0.601. Thanks SREZIC / #134375.
|
||||
- Fix some typos in bin/ncnetstat docs. Thanks RSAVAGE / #134382.
|
||||
|
||||
0.7.0 2021-02-19/06:30
|
||||
- Revert to lsof on FreeBSD given formatting problems with
|
||||
sockstat on FreeBSD with long IPv6 addresses.
|
||||
|
||||
0.6.4 2021-02-17/04:00
|
||||
- Change use if around to play friendly with older versions of Perl.
|
||||
|
||||
0.6.3 2021-02-16/10:30
|
||||
- Fix at runtime module use to actually work now. Thanks Grinnz, Botje!
|
||||
|
||||
0.6.2 2021-02-16/02:30
|
||||
- Remove it accidentally using Net::Conection::lsof always.
|
||||
|
||||
0.6.1 2021-02-08/20:00
|
||||
- Accidentally inverted the OS check for FreeBSD in Makefile.PL.
|
||||
|
||||
0.6.0 2021-02-08/08:00
|
||||
- Now uses sockstat on FreeBSD.
|
||||
- Make --pct, -C, --Cl, and -W XORable via $ENV
|
||||
|
||||
0.5.0 2019-09-03/03:30
|
||||
- Add the arg no_pid_user.
|
||||
|
||||
0.4.2 2019-08-20/02:00
|
||||
- Add a missing column style option.
|
||||
- Depend on Data::Unixish::Apply, #130303.
|
||||
- Clean up column code.
|
||||
|
||||
0.4.1 2019-08-14/05:00
|
||||
- Actually use Net::Connection->proc now.
|
||||
|
||||
0.4.0 2019-08-14/04:30
|
||||
- Convert to Text::ANSITable for line wrapping with --Cl
|
||||
|
||||
0.3.0 2019-08-12/06:00
|
||||
- Add support for wchan, pctmem, and pctcpu.
|
||||
|
||||
|
|
|
@ -7,3 +7,5 @@ t/00-load.t
|
|||
t/manifest.t
|
||||
t/pod-coverage.t
|
||||
t/pod.t
|
||||
bin/ncnetstat
|
||||
bin/.exists
|
||||
|
|
|
@ -4,48 +4,56 @@ use warnings;
|
|||
use ExtUtils::MakeMaker;
|
||||
|
||||
my %WriteMakefileArgs = (
|
||||
NAME => 'Net::Connection::ncnetstat',
|
||||
AUTHOR => q{Zane C. Bowers-Hadley <vvelox@vvelox.net>},
|
||||
VERSION_FROM => 'lib/Net/Connection/ncnetstat.pm',
|
||||
ABSTRACT_FROM => 'lib/Net/Connection/ncnetstat.pm',
|
||||
LICENSE => 'artistic_2',
|
||||
MIN_PERL_VERSION => '5.006',
|
||||
INST_SCRIPT => 'bin',
|
||||
CONFIGURE_REQUIRES => {
|
||||
'ExtUtils::MakeMaker' => '0',
|
||||
},
|
||||
TEST_REQUIRES => {
|
||||
'Test::More' => '0',
|
||||
},
|
||||
PREREQ_PM => {
|
||||
'Net::Connection'=>'0.1.0',
|
||||
'Net::Connection::lsof'=>'0.0.2',
|
||||
'Net::Connection::Match'=>'0.2.0',
|
||||
'Net::Connection::Sort'=>'0.0.0',
|
||||
'Term::ANSIColor'=>'4.06',
|
||||
'Text::Table'=>'1.133',
|
||||
'Getopt::Long'=>'0.0.0',
|
||||
},
|
||||
dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
|
||||
clean => { FILES => 'Net-Connection-ncnetstat-*' },
|
||||
);
|
||||
NAME => 'Net::Connection::ncnetstat',
|
||||
AUTHOR => q{Zane C. Bowers-Hadley <vvelox@vvelox.net>},
|
||||
VERSION_FROM => 'lib/Net/Connection/ncnetstat.pm',
|
||||
ABSTRACT_FROM => 'lib/Net/Connection/ncnetstat.pm',
|
||||
LICENSE => 'artistic_2',
|
||||
MIN_PERL_VERSION => '5.006',
|
||||
INST_SCRIPT => 'bin',
|
||||
CONFIGURE_REQUIRES => {
|
||||
'ExtUtils::MakeMaker' => '0',
|
||||
},
|
||||
TEST_REQUIRES => {
|
||||
'Test::More' => '0',
|
||||
},
|
||||
PREREQ_PM => {
|
||||
'Net::Connection' => '0.2.0',
|
||||
'Net::Connection::lsof' => '0.3.0',
|
||||
'Net::Connection::Match' => '0.5.0',
|
||||
'Net::Connection::Sort' => '0.1.1',
|
||||
'Term::ANSIColor' => '4.06',
|
||||
'Text::ANSITable' => '0.601',
|
||||
'Getopt::Long' => '0.0.0',
|
||||
'Data::Unixish::Apply' => '1.570',
|
||||
},
|
||||
dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
|
||||
clean => { FILES => 'Net-Connection-ncnetstat-*' },
|
||||
);
|
||||
|
||||
#if ( $^O =~ /freebsd/ ) {
|
||||
# $WriteMakefileArgs{PREREQ_PM}{'Net::Connection::FreeBSD_sockstat'} = '0.0.1';
|
||||
#}
|
||||
#else {
|
||||
$WriteMakefileArgs{PREREQ_PM}{'Net::Connection::lsof'} = '0.2.0';
|
||||
#}
|
||||
|
||||
# Compatibility with old versions of ExtUtils::MakeMaker
|
||||
unless (eval { ExtUtils::MakeMaker->VERSION('6.64'); 1 }) {
|
||||
my $test_requires = delete $WriteMakefileArgs{TEST_REQUIRES} || {};
|
||||
@{$WriteMakefileArgs{PREREQ_PM}}{keys %$test_requires} = values %$test_requires;
|
||||
unless ( eval { ExtUtils::MakeMaker->VERSION('6.64'); 1 } ) {
|
||||
my $test_requires = delete $WriteMakefileArgs{TEST_REQUIRES} || {};
|
||||
@{ $WriteMakefileArgs{PREREQ_PM} }{ keys %$test_requires } = values %$test_requires;
|
||||
}
|
||||
|
||||
unless (eval { ExtUtils::MakeMaker->VERSION('6.55_03'); 1 }) {
|
||||
my $build_requires = delete $WriteMakefileArgs{BUILD_REQUIRES} || {};
|
||||
@{$WriteMakefileArgs{PREREQ_PM}}{keys %$build_requires} = values %$build_requires;
|
||||
unless ( eval { ExtUtils::MakeMaker->VERSION('6.55_03'); 1 } ) {
|
||||
my $build_requires = delete $WriteMakefileArgs{BUILD_REQUIRES} || {};
|
||||
@{ $WriteMakefileArgs{PREREQ_PM} }{ keys %$build_requires } = values %$build_requires;
|
||||
}
|
||||
|
||||
delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
|
||||
unless eval { ExtUtils::MakeMaker->VERSION('6.52'); 1 };
|
||||
unless eval { ExtUtils::MakeMaker->VERSION('6.52'); 1 };
|
||||
delete $WriteMakefileArgs{MIN_PERL_VERSION}
|
||||
unless eval { ExtUtils::MakeMaker->VERSION('6.48'); 1 };
|
||||
unless eval { ExtUtils::MakeMaker->VERSION('6.48'); 1 };
|
||||
delete $WriteMakefileArgs{LICENSE}
|
||||
unless eval { ExtUtils::MakeMaker->VERSION('6.31'); 1 };
|
||||
unless eval { ExtUtils::MakeMaker->VERSION('6.31'); 1 };
|
||||
|
||||
WriteMakefile(%WriteMakefileArgs);
|
||||
|
|
|
@ -6,13 +6,14 @@ use Getopt::Long;
|
|||
use Net::Connection::ncnetstat;
|
||||
|
||||
sub version{
|
||||
print "ncnetstat v. 0.2.0\n";
|
||||
print "ncnetstat v. 0.4.0\n";
|
||||
}
|
||||
|
||||
sub help{
|
||||
print '
|
||||
-a Show all connections.
|
||||
--drp Do not resolve port names.
|
||||
--dump Show the Net::Connection::Match filter and exit.
|
||||
-i Invert the sort.
|
||||
-l Show the listening ports.
|
||||
-n Do not resolve the PTRs.
|
||||
|
@ -88,6 +89,7 @@ ptr_f foreign PTR
|
|||
ptr_l local PTR
|
||||
state state
|
||||
uid user ID
|
||||
unsorted Unsorted ((default))
|
||||
user username
|
||||
|
||||
For CPU, memory, PID, and UID searches, the equalities below can be
|
||||
|
@ -105,7 +107,7 @@ my $udp=0;
|
|||
my $help=0;
|
||||
my $version=0;
|
||||
my $dont_resolve_ports=0;
|
||||
my $sort='host_fl';
|
||||
my $sort='unsorted';
|
||||
my $cidr_string;
|
||||
my $lcidr_string;
|
||||
my $rcidr_string;
|
||||
|
@ -154,6 +156,7 @@ my $cpu_string;
|
|||
my $cpu_invert=0;
|
||||
my $mem_string;
|
||||
my $mem_invert=0;
|
||||
my $dump=0;
|
||||
|
||||
# get the commandline options
|
||||
Getopt::Long::Configure ('no_ignore_case');
|
||||
|
@ -214,6 +217,7 @@ GetOptions(
|
|||
'cpui' => \$cpu_invert,
|
||||
'mem=s' => \$mem_string,
|
||||
'memi' => \$mem_invert,
|
||||
'dump' => \$dump,
|
||||
);
|
||||
|
||||
my @filters;
|
||||
|
@ -230,28 +234,46 @@ if ( $help ){
|
|||
exit;
|
||||
}
|
||||
|
||||
#
|
||||
# XOR various command line options
|
||||
#
|
||||
if (defined( $ENV{'ncnetstat_pct'} )) {
|
||||
$pct_show= $pct_show ^ $ENV{'ncnetstat_pct'};
|
||||
}
|
||||
if (defined( $ENV{'ncnetstat_C'} )) {
|
||||
$command = $command ^ $ENV{'ncnetstat_C'};
|
||||
}
|
||||
if (defined( $ENV{'ncnetstat_Cl'} )) {
|
||||
$command_long = $command_long ^ $ENV{'ncnetstat_Cl'};
|
||||
}
|
||||
if (defined( $ENV{'ncnetstat_W'} )) {
|
||||
$wchan_show = $wchan_show ^ $ENV{'ncnetstat_W'};
|
||||
}
|
||||
|
||||
|
||||
# add the filters for the -l and -a option
|
||||
if (
|
||||
( ! $all ) &&
|
||||
( ! $listening )
|
||||
){
|
||||
# If -a is not given, we don't want the listen ports
|
||||
push( @filters, {
|
||||
push( @filters,
|
||||
{
|
||||
type=>'Ports',
|
||||
invert=>1,
|
||||
args=>{
|
||||
ports=>[
|
||||
'*',
|
||||
],
|
||||
}
|
||||
},
|
||||
{
|
||||
type=>'States',
|
||||
invert=>1,
|
||||
args=>{
|
||||
states=>['LISTEN']
|
||||
}
|
||||
},
|
||||
{
|
||||
type=>'Ports',
|
||||
invert=>1,
|
||||
args=>{
|
||||
fports=>[
|
||||
'*',
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}elsif(
|
||||
$listening &&
|
||||
|
@ -608,6 +630,13 @@ if ( $command_long && ! $command ){
|
|||
$command=1;
|
||||
}
|
||||
|
||||
#dump the filters if asked
|
||||
if ($dump) {
|
||||
use Data::Dumper;
|
||||
print Dumper( \@filters );
|
||||
exit;
|
||||
}
|
||||
|
||||
my $ncnetstat=Net::Connection::ncnetstat->new(
|
||||
{
|
||||
ptr=>$ptr,
|
||||
|
@ -887,21 +916,45 @@ A space-separated list of nameservers to query used by L<Net::DNS::Resolver>.
|
|||
There are a few more possible ones, but this is the most useful one and that documentation
|
||||
really belongs to that module.
|
||||
|
||||
=head2 ncnetstat_C
|
||||
|
||||
Used to xor the -C switch.
|
||||
|
||||
Set to either 0 or 1, boolean, for setting the default.
|
||||
|
||||
=head2 ncnetstat_Cl
|
||||
|
||||
Used to xor the --Cl switch.
|
||||
|
||||
Set to either 0 or 1, boolean, for setting the default.
|
||||
|
||||
=head2 ncnetstat_W
|
||||
|
||||
Used to xor the -W switch.
|
||||
|
||||
Set to either 0 or 1, boolean, for setting the default.
|
||||
|
||||
=head2 ncnetstat_pct
|
||||
|
||||
Used to xor the --pct switch.
|
||||
|
||||
Set to either 0 or 1, boolean, for setting the default.
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
ncnestat -s established,time_wait
|
||||
ncnetstat -s established,time_wait
|
||||
|
||||
Return a list of connection that are in the established or time_wait state.
|
||||
|
||||
ncnestat -c ::/0
|
||||
ncnetstat -c ::/0
|
||||
|
||||
Return a list of all IPv6 addresses.
|
||||
|
||||
ncnestat -c ::1/128,127.0.0.1/32
|
||||
ncnetstat -c ::1/128,127.0.0.1/32
|
||||
|
||||
Return all connections to localhost.
|
||||
|
||||
ncnestat -c 192.168.15.2/32 -l
|
||||
ncnetstat -c 192.168.15.2/32 -l
|
||||
|
||||
Display all connections listening explicitly on 192.168.15.2.
|
||||
|
||||
|
|
|
@ -6,10 +6,14 @@ use warnings;
|
|||
use Net::Connection;
|
||||
use Net::Connection::Match;
|
||||
use Net::Connection::Sort;
|
||||
use Net::Connection::lsof;
|
||||
use Text::Table;
|
||||
use Term::ANSIColor;
|
||||
use Proc::ProcessTable;
|
||||
use Text::ANSITable;
|
||||
|
||||
# use Net::Connection::FreeBSD_sockstat if possible
|
||||
#use if $^O eq 'freebsd', 'Net::Connection::FreeBSD_sockstat';
|
||||
#use if $^O ne 'freebsd', 'Net::Connection::lsof';
|
||||
use Net::Connection::lsof;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
@ -17,11 +21,11 @@ Net::Connection::ncnetstat - The backend for ncnetstat, the colorized and enhanc
|
|||
|
||||
=head1 VERSION
|
||||
|
||||
Version 0.3.0
|
||||
Version 0.8.0
|
||||
|
||||
=cut
|
||||
|
||||
our $VERSION = '0.3.0';
|
||||
our $VERSION = '0.8.0';
|
||||
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
@ -84,6 +88,10 @@ This is the hash to pass to L<Net::Connection::Match>.
|
|||
|
||||
By default this is undef and that module won't be used.
|
||||
|
||||
=head4 no_pid_user
|
||||
|
||||
Don't show the PID or UID/user colomn.
|
||||
|
||||
=head4 sorter
|
||||
|
||||
This is what is to be passed to L<Net::Connection::Sorter>.
|
||||
|
@ -91,58 +99,63 @@ This is what is to be passed to L<Net::Connection::Sorter>.
|
|||
The default is as below.
|
||||
|
||||
{
|
||||
type=>'host_fl',
|
||||
type=>'unsorted',
|
||||
invert=>0,
|
||||
}
|
||||
|
||||
=cut
|
||||
|
||||
sub new{
|
||||
sub new {
|
||||
my %args;
|
||||
if(defined($_[1])){
|
||||
%args= %{$_[1]};
|
||||
};
|
||||
if ( defined( $_[1] ) ) {
|
||||
%args = %{ $_[1] };
|
||||
}
|
||||
|
||||
if (! defined( $args{sorter} ) ){
|
||||
$args{sorter}={
|
||||
type=>'host_fl',
|
||||
invert=>0,
|
||||
};
|
||||
if ( !defined( $args{sorter} ) ) {
|
||||
$args{sorter} = {
|
||||
type => 'unsorted',
|
||||
invert => 0,
|
||||
};
|
||||
}
|
||||
|
||||
my $self = {
|
||||
invert=>0,
|
||||
sorter=>Net::Connection::Sort->new( $args{sorter} ),
|
||||
ptr=>1,
|
||||
command=>0,
|
||||
command_long=>0,
|
||||
wchan=>0,
|
||||
pct=>0,
|
||||
};
|
||||
bless $self;
|
||||
invert => 0,
|
||||
sorter => Net::Connection::Sort->new( $args{sorter} ),
|
||||
ptr => 1,
|
||||
command => 0,
|
||||
command_long => 0,
|
||||
wchan => 0,
|
||||
pct => 0,
|
||||
no_pid_user => 0,
|
||||
};
|
||||
bless $self;
|
||||
|
||||
if ( defined( $args{match} ) ){
|
||||
$self->{match}=Net::Connection::Match->new( $args{match} );
|
||||
if ( defined( $args{match} ) ) {
|
||||
$self->{match} = Net::Connection::Match->new( $args{match} );
|
||||
}
|
||||
|
||||
if ( defined( $args{ptr} )){
|
||||
$self->{ptr}=$args{ptr};
|
||||
if ( defined( $args{ptr} ) ) {
|
||||
$self->{ptr} = $args{ptr};
|
||||
}
|
||||
|
||||
if ( defined( $args{command} ) ){
|
||||
$self->{command}=$args{command};
|
||||
if ( defined( $args{command} ) ) {
|
||||
$self->{command} = $args{command};
|
||||
}
|
||||
|
||||
if ( defined( $args{pct} ) ){
|
||||
$self->{pct}=$args{pct};
|
||||
if ( defined( $args{pct} ) ) {
|
||||
$self->{pct} = $args{pct};
|
||||
}
|
||||
|
||||
if ( defined( $args{wchan} ) ){
|
||||
$self->{wchan}=$args{wchan};
|
||||
if ( defined( $args{wchan} ) ) {
|
||||
$self->{wchan} = $args{wchan};
|
||||
}
|
||||
|
||||
if ( defined( $args{command_long} ) ){
|
||||
$self->{command_long}=$args{command_long};
|
||||
if ( defined( $args{command_long} ) ) {
|
||||
$self->{command_long} = $args{command_long};
|
||||
}
|
||||
|
||||
if ( defined( $args{no_pid_user} ) ) {
|
||||
$self->{no_pid_user} = $args{no_pid_user};
|
||||
}
|
||||
|
||||
return $self;
|
||||
|
@ -156,202 +169,291 @@ This runs it and returns a string.
|
|||
|
||||
=cut
|
||||
|
||||
sub run{
|
||||
my $self=$_[0];
|
||||
|
||||
my @objects = &lsof_to_nc_objects;
|
||||
sub run {
|
||||
my $self = $_[0];
|
||||
|
||||
my @objects;
|
||||
# if ( $^O !~ /freebsd/ ) {
|
||||
@objects = &lsof_to_nc_objects;
|
||||
# }
|
||||
# else {
|
||||
# @objects = &sockstat_to_nc_objects;
|
||||
# }
|
||||
|
||||
my @found;
|
||||
if (defined( $self->{match} )){
|
||||
foreach my $conn (@objects){
|
||||
if( $self->{match}->match( $conn ) ){
|
||||
if ( defined( $self->{match} ) ) {
|
||||
foreach my $conn (@objects) {
|
||||
if ( $self->{match}->match($conn) ) {
|
||||
push( @found, $conn );
|
||||
}
|
||||
}
|
||||
}else{
|
||||
@found=@objects;
|
||||
}
|
||||
else {
|
||||
@found = @objects;
|
||||
}
|
||||
|
||||
@found=$self->{sorter}->sorter( \@found );
|
||||
@found = $self->{sorter}->sorter( \@found );
|
||||
|
||||
my @headers=(
|
||||
color('underline white').'Proto'.color('reset'),
|
||||
color('underline white').'User'.color('reset'),
|
||||
color('underline white').'PID'.color('reset'),
|
||||
color('underline white').'Local Host'.color('reset'),
|
||||
color('underline white').'Port'.color('reset'),
|
||||
color('underline white').'Remote Host'.color('reset'),
|
||||
color('underline white').'Port'.color('reset'),
|
||||
color('underline white').'State'.color('reset'),
|
||||
);
|
||||
my $tb = Text::ANSITable->new;
|
||||
$tb->border_style('ASCII::None');
|
||||
$tb->color_theme('NoColor');
|
||||
|
||||
if ( $self->{wchan} ){
|
||||
push( @headers, color('underline white').'WChan'.color('reset') );
|
||||
my @headers;
|
||||
my $header_int = 0;
|
||||
push( @headers, 'Proto' );
|
||||
$tb->set_column_style( $header_int, pad => 0 );
|
||||
$header_int++;
|
||||
if ( !$self->{no_pid_user} ) {
|
||||
push( @headers, 'User' );
|
||||
$tb->set_column_style( $header_int, pad => 1 );
|
||||
$header_int++;
|
||||
push( @headers, 'PID' );
|
||||
$tb->set_column_style( $header_int, pad => 0 );
|
||||
$header_int++;
|
||||
}
|
||||
push( @headers, 'Local Host' );
|
||||
$tb->set_column_style( $header_int, pad => 1, formats => [ [ wrap => { ansi => 1, mb => 1 } ] ] );
|
||||
$header_int++;
|
||||
push( @headers, 'L Port' );
|
||||
$tb->set_column_style( $header_int, pad => 0 );
|
||||
$header_int++;
|
||||
push( @headers, 'Remote Host' );
|
||||
$tb->set_column_style( $header_int, pad => 1, formats => [ [ wrap => { ansi => 1, mb => 1 } ] ] );
|
||||
$header_int++;
|
||||
push( @headers, 'R Port' );
|
||||
$tb->set_column_style( $header_int, pad => 0 );
|
||||
$header_int++;
|
||||
push( @headers, 'State' );
|
||||
$tb->set_column_style( $header_int, pad => 1 );
|
||||
$header_int++;
|
||||
|
||||
my $padding = 0;
|
||||
if ( $self->{wchan} ) {
|
||||
if ( ( $header_int % 2 ) != 0 ) {
|
||||
$padding = 1;
|
||||
}
|
||||
push( @headers, 'WChan' );
|
||||
$tb->set_column_style( $header_int, pad => $padding );
|
||||
$header_int++;
|
||||
}
|
||||
|
||||
if ( $self->{pct} ){
|
||||
push( @headers, color('underline white').'CPU%'.color('reset') );
|
||||
push( @headers, color('underline white').'Mem%'.color('reset') );
|
||||
if ( $self->{pct} ) {
|
||||
if ( ( $header_int % 2 ) != 0 ) {
|
||||
$padding = 1;
|
||||
}
|
||||
else {
|
||||
$padding = 0;
|
||||
}
|
||||
push( @headers, 'CPU%' );
|
||||
$tb->set_column_style( $header_int, pad => $padding );
|
||||
$header_int++;
|
||||
if ( ( $header_int % 2 ) != 0 ) {
|
||||
$padding = 1;
|
||||
}
|
||||
else {
|
||||
$padding = 0;
|
||||
}
|
||||
push( @headers, 'Mem%' );
|
||||
$tb->set_column_style( $header_int, pad => $padding );
|
||||
$header_int++;
|
||||
}
|
||||
|
||||
if ( $self->{command} ){
|
||||
push( @headers, color('underline white').'Command'.color('reset') );
|
||||
if ( $self->{command} ) {
|
||||
if ( ( $header_int % 2 ) != 0 ) {
|
||||
$padding = 1;
|
||||
}
|
||||
else {
|
||||
$padding = 0;
|
||||
}
|
||||
push( @headers, 'Command' );
|
||||
$tb->set_column_style( $header_int, pad => $padding, formats => [ [ wrap => { ansi => 1, mb => 1 } ] ] );
|
||||
$header_int++;
|
||||
}
|
||||
|
||||
my $tb = Text::Table->new( @headers );
|
||||
$tb->set_column_style( 4, pad => 0 );
|
||||
$tb->set_column_style( 5, pad => 1, formats => [ [ wrap => { ansi => 1, mb => 1 } ] ] );
|
||||
$tb->set_column_style( 6, pad => 0 );
|
||||
$tb->set_column_style( 7, pad => 1 );
|
||||
$tb->set_column_style( 8, pad => 0 );
|
||||
$tb->set_column_style( 9, pad => 1 );
|
||||
$tb->set_column_style( 10, pad => 0 );
|
||||
$tb->set_column_style( 11, pad => 1, formats => [ [ wrap => { ansi => 1, mb => 1 } ] ] );
|
||||
$tb->set_column_style( 12, pad => 0 );
|
||||
$tb->set_column_style( 13, pad => 1 );
|
||||
|
||||
$tb->columns( \@headers );
|
||||
|
||||
# process table stuff if needed
|
||||
my $ppt;
|
||||
my $proctable;
|
||||
my %cmd_cache;
|
||||
if ( $self->{command} ){
|
||||
$ppt=Proc::ProcessTable->new;
|
||||
$proctable=$ppt->table;
|
||||
if ( $self->{command} ) {
|
||||
$ppt = Proc::ProcessTable->new;
|
||||
$proctable = $ppt->table;
|
||||
}
|
||||
|
||||
my @td;
|
||||
foreach my $conn ( @found ){
|
||||
my @new_line=(
|
||||
color('bright_yellow').$conn->proto.color('reset'),
|
||||
);
|
||||
foreach my $conn (@found) {
|
||||
my @new_line = ( color('bright_yellow') . $conn->proto . color('reset'), );
|
||||
|
||||
# handle adding the username or UID if we have one
|
||||
if ( defined( $conn->username ) ){
|
||||
push( @new_line, color('bright_cyan').$conn->username.color('reset'));
|
||||
}else{
|
||||
if ( defined( $conn->uid ) ){
|
||||
push( @new_line, color('bright_cyan').$conn->uid.color('reset'));
|
||||
}else{
|
||||
push( @new_line, '');
|
||||
# don't add the PID or user if requested to
|
||||
if ( !$self->{no_pid_user} ) {
|
||||
|
||||
# handle adding the username or UID if we have one
|
||||
if ( defined( $conn->username ) ) {
|
||||
push( @new_line, color('bright_cyan') . $conn->username . color('reset') );
|
||||
}
|
||||
else {
|
||||
if ( defined( $conn->uid ) ) {
|
||||
push( @new_line, color('bright_cyan') . $conn->uid . color('reset') );
|
||||
}
|
||||
else {
|
||||
push( @new_line, '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# handle adding the PID if we have one
|
||||
if ( defined( $conn->pid ) ){
|
||||
push( @new_line, color('bright_red').$conn->pid.color('reset'));
|
||||
$conn->pid;
|
||||
}else{
|
||||
push( @new_line, '');
|
||||
# handle adding the PID if we have one
|
||||
if ( defined( $conn->pid ) ) {
|
||||
push( @new_line, color('bright_red') . $conn->pid . color('reset') );
|
||||
$conn->pid;
|
||||
}
|
||||
else {
|
||||
push( @new_line, '' );
|
||||
}
|
||||
}
|
||||
|
||||
# Figure out what we are using for the local host
|
||||
my $local;
|
||||
if ( defined( $conn->local_ptr ) && $self->{ptr} ){
|
||||
$local=$conn->local_ptr;
|
||||
}else{
|
||||
$local=$conn->local_host;
|
||||
if ( defined( $conn->local_ptr ) && $self->{ptr} ) {
|
||||
$local = $conn->local_ptr;
|
||||
}
|
||||
else {
|
||||
$local = $conn->local_host;
|
||||
}
|
||||
|
||||
# Figure out what we are using for the foriegn host
|
||||
my $foreign;
|
||||
if ( defined( $conn->foreign_ptr ) && $self->{ptr} ){
|
||||
$foreign=$conn->foreign_ptr;
|
||||
}else{
|
||||
$foreign=$conn->foreign_host;
|
||||
if ( defined( $conn->foreign_ptr ) && $self->{ptr} ) {
|
||||
$foreign = $conn->foreign_ptr;
|
||||
}
|
||||
else {
|
||||
$foreign = $conn->foreign_host;
|
||||
}
|
||||
|
||||
# Figure out what we are using for the local port
|
||||
my $lport;
|
||||
if ( defined( $conn->local_port_name ) ){
|
||||
$lport=$conn->local_port_name;
|
||||
}else{
|
||||
$lport=$conn->local_port;
|
||||
if ( defined( $conn->local_port_name ) ) {
|
||||
$lport = $conn->local_port_name;
|
||||
}
|
||||
else {
|
||||
$lport = $conn->local_port;
|
||||
}
|
||||
|
||||
# Figure out what we are using for the foreign port
|
||||
my $fport;
|
||||
if ( defined( $conn->foreign_port_name ) ){
|
||||
$fport=$conn->foreign_port_name;
|
||||
}else{
|
||||
$fport=$conn->foreign_port;
|
||||
if ( defined( $conn->foreign_port_name ) ) {
|
||||
$fport = $conn->foreign_port_name;
|
||||
}
|
||||
else {
|
||||
$fport = $conn->foreign_port;
|
||||
}
|
||||
|
||||
push(
|
||||
@new_line,
|
||||
color('bright_green').$local.color('reset'),
|
||||
color('green').$lport.color('reset'),
|
||||
color('bright_magenta').$foreign.color('reset'),
|
||||
color('magenta').$fport.color('reset'),
|
||||
color('bright_blue').$conn->state.color('reset'),
|
||||
);
|
||||
push( @new_line,
|
||||
color('bright_green') . $local . color('reset'),
|
||||
color('green') . $lport . color('reset'),
|
||||
color('bright_magenta') . $foreign . color('reset'),
|
||||
color('magenta') . $fport . color('reset'),
|
||||
color('bright_blue') . $conn->state . color('reset'),
|
||||
);
|
||||
|
||||
# handle the wchan bit if needed
|
||||
if (
|
||||
$self->{wchan} &&
|
||||
defined( $conn->wchan )
|
||||
){
|
||||
push( @new_line, color('bright_yellow').$conn->wchan.color('reset') );
|
||||
if ( $self->{wchan}
|
||||
&& defined( $conn->wchan ) )
|
||||
{
|
||||
push( @new_line, color('bright_yellow') . $conn->wchan . color('reset') );
|
||||
}
|
||||
|
||||
# handle the percent stuff if needed
|
||||
if (
|
||||
$self->{pct} &&
|
||||
defined( $conn->pctcpu )
|
||||
){
|
||||
push( @new_line, color('bright_cyan').sprintf('%.2f',$conn->pctcpu).color('reset') );
|
||||
if ( $self->{pct}
|
||||
&& defined( $conn->pctcpu ) )
|
||||
{
|
||||
push( @new_line, color('bright_cyan') . sprintf( '%.2f', $conn->pctcpu ) . color('reset') );
|
||||
}
|
||||
|
||||
# handle the percent stuff if needed
|
||||
if (
|
||||
$self->{pct} &&
|
||||
defined( $conn->pctmem )
|
||||
){
|
||||
push( @new_line, color('bright_green').sprintf('%.2f', $conn->pctmem).color('reset') );
|
||||
if ( $self->{pct}
|
||||
&& defined( $conn->pctmem ) )
|
||||
{
|
||||
push( @new_line, color('bright_green') . sprintf( '%.2f', $conn->pctmem ) . color('reset') );
|
||||
}
|
||||
|
||||
# handle the command portion if needed
|
||||
if (
|
||||
defined( $conn->pid ) &&
|
||||
$self->{command}
|
||||
){
|
||||
if ( defined( $conn->pid )
|
||||
&& $self->{command} )
|
||||
{
|
||||
|
||||
my $loop=1;
|
||||
my $proc=0;
|
||||
while (
|
||||
defined( $proctable->[ $proc ] ) &&
|
||||
$loop
|
||||
){
|
||||
my $loop = 1;
|
||||
my $proc = 0;
|
||||
while ( defined( $proctable->[$proc] )
|
||||
&& $loop )
|
||||
{
|
||||
my $command;
|
||||
if (defined( $cmd_cache{$conn->pid} ) ){
|
||||
push( @new_line, color('bright_red').$cmd_cache{$conn->pid}.color('reset') );
|
||||
$loop=0;
|
||||
}elsif( $proctable->[ $proc ]->pid eq $conn->pid ){
|
||||
if ( $proctable->[ $proc ]->{'cmndline'} =~ /^$/ ){
|
||||
if ( defined( $cmd_cache{ $conn->pid } ) ) {
|
||||
push( @new_line, color('bright_red') . $cmd_cache{ $conn->pid } . color('reset') );
|
||||
$loop = 0;
|
||||
}
|
||||
elsif ( defined( $conn->proc ) ) {
|
||||
my $command = $conn->proc;
|
||||
if ( !$self->{command_long} ) {
|
||||
$command =~ s/\ .*//;
|
||||
}
|
||||
$cmd_cache{ $conn->pid } = $command;
|
||||
push( @new_line, color('bright_red') . $cmd_cache{ $conn->pid } . color('reset') );
|
||||
$loop = 0,;
|
||||
}
|
||||
elsif ( $proctable->[$proc]->pid eq $conn->pid ) {
|
||||
if ( $proctable->[$proc]->{'cmndline'} =~ /^$/ ) {
|
||||
|
||||
#kernel process
|
||||
$cmd_cache{$conn->pid}=color('bright_red').'['.$proctable->[ $proc ]->{'fname'}.']'.color('reset');
|
||||
}elsif( $self->{command_long} ){
|
||||
$cmd_cache{$conn->pid}=color('bright_red').$proctable->[ $proc ]->{'cmndline'}.color('reset');
|
||||
}elsif( $proctable->[ $proc ]->{'cmndline'} =~ /^\//){
|
||||
$cmd_cache{ $conn->pid }
|
||||
= color('bright_red') . '[' . $proctable->[$proc]->{'fname'} . ']' . color('reset');
|
||||
}
|
||||
elsif ( $self->{command_long} ) {
|
||||
$cmd_cache{ $conn->pid }
|
||||
= color('bright_red') . $proctable->[$proc]->{'cmndline'} . color('reset');
|
||||
}
|
||||
elsif ( $proctable->[$proc]->{'cmndline'} =~ /^\// ) {
|
||||
|
||||
# something ran with a complete path
|
||||
$cmd_cache{$conn->pid}=color('bright_red').$proctable->[ $proc ]->{'fname'}.color('reset');
|
||||
}else{
|
||||
$cmd_cache{ $conn->pid }
|
||||
= color('bright_red') . $proctable->[$proc]->{'fname'} . color('reset');
|
||||
}
|
||||
else {
|
||||
# likely a thread or the like... such as dovecot/auth
|
||||
# just trunkcat everything after the space
|
||||
my $cmd=$proctable->[ $proc ]->{'cmndline'};
|
||||
$cmd=~s/\ +.*//g;
|
||||
$cmd_cache{$conn->pid}=color('bright_red').$cmd.color('reset');
|
||||
my $cmd = $proctable->[$proc]->{'cmndline'};
|
||||
$cmd =~ s/\ +.*//g;
|
||||
$cmd_cache{ $conn->pid } = color('bright_red') . $cmd . color('reset');
|
||||
}
|
||||
|
||||
push( @new_line, $cmd_cache{$conn->pid} );
|
||||
$loop=0;
|
||||
push( @new_line, $cmd_cache{ $conn->pid } );
|
||||
$loop = 0;
|
||||
}
|
||||
|
||||
$proc++;
|
||||
}
|
||||
|
||||
}elsif(
|
||||
( !defined( $conn->pid ) ) &&
|
||||
$self->{command}
|
||||
){
|
||||
push( @new_line, '');
|
||||
}
|
||||
elsif ( ( !defined( $conn->pid ) )
|
||||
&& $self->{command} )
|
||||
{
|
||||
push( @new_line, '' );
|
||||
}
|
||||
|
||||
push( @td, \@new_line );
|
||||
$tb->add_row( \@new_line );
|
||||
}
|
||||
|
||||
$tb->load( @td );
|
||||
|
||||
return $tb;
|
||||
return $tb->draw;
|
||||
}
|
||||
|
||||
=head1 TODO
|
||||
|
@ -388,14 +490,6 @@ You can also look for information at:
|
|||
|
||||
L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-Connection-ncnetstat>
|
||||
|
||||
=item * AnnoCPAN: Annotated CPAN documentation
|
||||
|
||||
L<http://annocpan.org/dist/Net-Connection-ncnetstat>
|
||||
|
||||
=item * CPAN Ratings
|
||||
|
||||
L<https://cpanratings.perl.org/d/Net-Connection-ncnetstat>
|
||||
|
||||
=item * Search CPAN
|
||||
|
||||
L<https://metacpan.org/release/Net-Connection-ncnetstat>
|
||||
|
|
|
@ -10,7 +10,7 @@ BEGIN {
|
|||
use_ok( 'Net::Connection::ncnetstat' ) || print "Bail out!\n";
|
||||
}
|
||||
|
||||
my $output_raw=`lsof -i UDP -i TCP -n -l -P`;
|
||||
my $output_raw=`lsof -i UDP -i TCP -n -l -P 2> /dev/null`;
|
||||
if (
|
||||
( $? eq 0 ) ||
|
||||
(
|
||||
|
@ -18,7 +18,7 @@ if (
|
|||
( $? eq 256 )
|
||||
)
|
||||
){
|
||||
$extra_tests=2;
|
||||
$extra_tests=1;
|
||||
my $worked=0;
|
||||
my $ncnetstat;
|
||||
my $tb;
|
||||
|
@ -28,7 +28,6 @@ if (
|
|||
$worked=1;
|
||||
};
|
||||
ok( $worked eq '1', 'run test') or diag("run died with ".$@);
|
||||
ok( ref($tb) eq 'Text::Table', 'run ref test') or diag("run did not return a Text::Table object");
|
||||
}else{
|
||||
diag('No lsof installed on this system or "lsof -i UDP -i TCP -n -l -P" does not work');
|
||||
}
|
||||
|
|
167
README.md
167
README.md
|
@ -8,90 +8,105 @@ The search criteria can be any of the following.
|
|||
|
||||
* CIDR
|
||||
* Command
|
||||
* CPU usage percent
|
||||
* port
|
||||
* host
|
||||
* memory usage percent
|
||||
* PID
|
||||
* PTR
|
||||
* state
|
||||
* UID
|
||||
* username
|
||||
* wait channel
|
||||
|
||||
# Command Line Options
|
||||
```
|
||||
-a Show all connections.
|
||||
--drp Do not resolve port names.
|
||||
-i Invert the sort.
|
||||
-l Show the listening ports.
|
||||
-n Do not resolve the PTRs.
|
||||
--nc Do not use colors.
|
||||
--pct Show memory and CPU usage percent.
|
||||
-S <sort> The Net::Connection::Sort to use.
|
||||
-t Show only TCP connections.
|
||||
-u Show only UDP connections.
|
||||
-W Show the wchan.
|
||||
|
||||
-a Show all connections.
|
||||
--drp Do not resolve port names.
|
||||
-i Invert the sort.
|
||||
-l Show the listening ports.
|
||||
-n Do not resolve the PTRs.
|
||||
--nc Do not use colors.
|
||||
-S <sort> The Net::Connection::Sort to use.
|
||||
-t Show only TCP connections.
|
||||
-u Show only UDP connections.
|
||||
|
||||
-c <CIDRs> A comma seperated list of CIDRs to search for.
|
||||
--ci Invert the CIDR search.
|
||||
|
||||
-C Show the command to the first space.
|
||||
--Cl Show the whole command.
|
||||
|
||||
--cmd <cmds> A comma seperated list of commands to search for.
|
||||
--cmdi Invert the command search.
|
||||
|
||||
-p <ports> A comma seperated list of ports to search for.
|
||||
--pi Invert the port search.
|
||||
|
||||
-P <protos> A comma seperated list of protocols to search for.
|
||||
--Pi Invert your protocol search.
|
||||
|
||||
--pid <pids> A comma separated list of PIDs to search for.
|
||||
--pidi Invert the pid search.
|
||||
|
||||
--ptrr <rgx> A comma seperated list of regex to use for a PTR search.
|
||||
--ptrri Invert the RegexPTR search.
|
||||
--lptrr <rgx> A comma seperated list of regex to use for a local PTR search.
|
||||
--lptrri Invert the local RegexPTR search.
|
||||
--rptrr <rgx> A comma seperated list of regex to use for a remote PTR search.
|
||||
--rptrri Invert the remote RegexPTR search.
|
||||
|
||||
--ptr <PTRs> A comma seperated list of PTRs to search for.
|
||||
--ptri Invert the PTR search.
|
||||
--lptr <PTRs> A comma seperated list of local PTRs to search for.
|
||||
--lptri Invert the local PTR search.
|
||||
--rptr <PTRs> A comma seperated list of remote PTRs to search for.
|
||||
--rptri Invert the remote PTR search.
|
||||
|
||||
-s <states> A comma seperated list of states to search for.
|
||||
--si Invert the state search.
|
||||
|
||||
-u <users> A comma seperated list of usernames to search for.
|
||||
--ui Invert the username search.
|
||||
|
||||
--uid <uids> A comma separated list of UIDs to search for.
|
||||
--uidi Invert the UID search.
|
||||
|
||||
The default available sort methods are as below.
|
||||
host_f foreign host
|
||||
host_fl foreign host, local host
|
||||
host_l local host
|
||||
host_lf local host, foreign host
|
||||
pid process ID
|
||||
port_f foreign port, numerically
|
||||
port_fa foreign port, alphabetically
|
||||
port_l local port, numerically
|
||||
port_la local port, alphabetically
|
||||
proto protocol
|
||||
ptr_f foreign PTR
|
||||
ptr_l local PTR
|
||||
state state
|
||||
uid user ID
|
||||
user username
|
||||
|
||||
For PID and UID searches, the equalities below can be used, by
|
||||
directly prepending them to the number.
|
||||
<
|
||||
<=
|
||||
>
|
||||
>=
|
||||
-c <CIDRs> A comma seperated list of CIDRs to search for.
|
||||
--ci Invert the CIDR search.
|
||||
|
||||
-C Show the command to the first space.
|
||||
--Cl Show the whole command.
|
||||
|
||||
--cmd <cmds> A comma seperated list of commands to search for.
|
||||
--cmdi Invert the command search.
|
||||
|
||||
--cpu <pct> Show connections belonging to procs matching this CPU usage percent.
|
||||
--cpui Invert the CPU search.
|
||||
|
||||
--mem <pct> Show connections belonging to procs matching this memory usage percent.
|
||||
--memi Invert the memory usage search.
|
||||
|
||||
-p <ports> A comma seperated list of ports to search for.
|
||||
--pi Invert the port search.
|
||||
|
||||
-P <protos> A comma seperated list of protocols to search for.
|
||||
--Pi Invert your protocol search.
|
||||
|
||||
--pid <pids> A comma separated list of PIDs to search for.
|
||||
--pidi Invert the pid search.
|
||||
|
||||
--ptrr <rgx> A comma seperated list of regex to use for a PTR search.
|
||||
--ptrri Invert the RegexPTR search.
|
||||
--lptrr <rgx> A comma seperated list of regex to use for a local PTR search.
|
||||
--lptrri Invert the local RegexPTR search.
|
||||
--rptrr <rgx> A comma seperated list of regex to use for a remote PTR search.
|
||||
--rptrri Invert the remote RegexPTR search.
|
||||
|
||||
--ptr <PTRs> A comma seperated list of PTRs to search for.
|
||||
--ptri Invert the PTR search.
|
||||
--lptr <PTRs> A comma seperated list of local PTRs to search for.
|
||||
--lptri Invert the local PTR search.
|
||||
--rptr <PTRs> A comma seperated list of remote PTRs to search for.
|
||||
--rptri Invert the remote PTR search.
|
||||
|
||||
-s <states> A comma seperated list of states to search for.
|
||||
--si Invert the state search.
|
||||
|
||||
-U <users> A comma seperated list of usernames to search for.
|
||||
--Ui Invert the username search.
|
||||
|
||||
--uid <uids> A comma separated list of UIDs to search for.
|
||||
--uidi Invert the UID search.
|
||||
|
||||
-w <rgx> A comma separated list of regexp to use for matching wchan values.
|
||||
--wi Invert the wchan search.
|
||||
|
||||
The default available sort methods are as below.
|
||||
host_f foreign host
|
||||
host_fl foreign host, local host
|
||||
host_l local host
|
||||
host_lf local host, foreign host
|
||||
pid process ID
|
||||
port_f foreign port, numerically
|
||||
port_fa foreign port, alphabetically
|
||||
port_l local port, numerically
|
||||
port_la local port, alphabetically
|
||||
proto protocol
|
||||
ptr_f foreign PTR
|
||||
ptr_l local PTR
|
||||
state state
|
||||
uid user ID
|
||||
user username
|
||||
|
||||
For CPU, memory, PID, and UID searches, the equalities below can be
|
||||
used, by directly prepending them to the number.
|
||||
<
|
||||
<=
|
||||
>
|
||||
>=
|
||||
```
|
||||
|
||||
# Examples
|
||||
|
||||
|
@ -134,6 +149,10 @@ PTR info and print the whole command.
|
|||
|
||||
Show every connecttion by the user www that is not a HTTP or HTTPS connection.
|
||||
|
||||
ncnetstat --cpu '>5' --Cl --pct -W
|
||||
|
||||
Search for connections from procs using more than 5% of the CPU time. Show memory
|
||||
and CPU usage as well whole command and wait channel.
|
||||
|
||||
# Installing
|
||||
|
||||
|
|
Loading…
Reference in New Issue