Compare commits

...

30 Commits

Author SHA1 Message Date
Zane C. B-H e519e0d7c7 quiet pointless lsof 2023-06-01 13:29:07 -05:00
Zane C. B-H 0ffb462b0b actually bump version 2023-06-01 13:28:07 -05:00
Zane C. B-H 55cd2535e3 update version info 2023-06-01 13:26:38 -05:00
Zane C. B-H 438d9b7d78 not changes and bump to 0.8.0 2023-06-01 13:20:08 -05:00
Zane C. B-H 9ecc05fe34 correct the change date 2021-02-19 07:48:04 -06:00
Zane C. B-H 680b4cbe62 misc updates 2021-02-19 07:41:32 -06:00
Zane C. B-H f3089ada01 note the changes 2021-02-19 06:23:43 -06:00
Zane C. B-H adc7220396 revert to lsof 2021-02-19 06:21:16 -06:00
Zane C. B-H 357d7e4dbe make play nicely with older versions of Perl on Linux 2021-02-17 03:29:04 -06:00
Zane C. B-H f8d90d9732 actually bump the version this time 2021-02-16 10:33:47 -06:00
Zane C. B-H ae3b04a789 fix use for on FreeBSD 2021-02-16 10:30:26 -06:00
Zane C. B-H 529fe02f05 no longer use lsof always 2021-02-16 02:33:54 -06:00
Zane C. B-H 37b53bf0d1 fix OS check, bump version, and note it 2021-02-08 23:05:11 -06:00
Zane C. B-H 84b13dba51 assorted updates to use sockstat and some XOR stuff 2021-02-08 06:44:46 -06:00
Zane C. B-H 703cd7c497 now works again, add --dump, and now uses sockstat on FreeBSD 2021-02-07 09:04:46 -06:00
Zane C. B-H 5d7b6abc87 note the changes and the arg 2019-09-03 03:32:28 -05:00
Zane C. B-H 50c0dd68c9 add the erquired bits for piddler 2019-08-31 00:12:13 -05:00
Zane C. B-H 85618c1cf0 actually add the version number to this one 2019-08-20 01:51:13 -05:00
Zane C. B-H 3c107240c0 note the changes 2019-08-20 01:50:42 -05:00
Zane C. B-H 469676b3b4 colum code cleanup 2019-08-20 01:44:32 -05:00
Zane C. B-H 62d6c30622 bump version 2019-08-20 00:50:07 -05:00
Zane C. B-H b53a481038 added Data::Unixish::Apply as a depend, Bug #130303 2019-08-20 00:48:16 -05:00
Zane C. B-H c7d9ece486 note the change 2019-08-14 05:19:56 -05:00
Zane C. B-H 736c1e71ef add a missing column style 2019-08-14 05:16:45 -05:00
Zane C. B-H 9c33541969 note the changes and actually use NC->proc 2019-08-14 05:02:00 -05:00
Zane C. B-H 4371e312ba note the changes and update the depends 2019-08-14 04:33:32 -05:00
Zane C. B-H bb355c9e2b now use Table::ANSITable 2019-08-14 04:29:44 -05:00
Zane C. B-H ec3bbe7a08 now require Net::Connection::lsof 0.1.1 or newer 2019-08-13 06:06:24 -05:00
Zane C. B-H c468f42c0b Update 'README.md' 2019-08-12 06:08:00 -05:00
Zane C. B-H 3f3e09cfcf Update 'README.md' 2019-08-12 06:06:56 -05:00
8 changed files with 511 additions and 295 deletions

View File

@ -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.

View File

@ -7,3 +7,5 @@ t/00-load.t
t/manifest.t
t/pod-coverage.t
t/pod.t
bin/ncnetstat
bin/.exists

View File

@ -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);

View File

View File

@ -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.

View File

@ -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>

View File

@ -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
View File

@ -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