Something that really annoys me when using the netstat(8)
command on Linux, it does not report the full command line with arguments of the process who owns the given network socket, just the process identifier and the program name in format PID/program name
.
By reading the source code of the netstat(8)
program from the busybox project here
311 len = snprintf(proc_pid_fname, sizeof(proc_pid_fname), "%s/cmdline", fileName);
312 n = open_read_close(proc_pid_fname, cmdline_buf, sizeof(cmdline_buf) - 1);
313 if (n < 0)
314 return FALSE;
315 cmdline_buf[n] = '\0';
316
317 /* go through all files in /proc/PID/fd and check whether they are sockets */
318 strcpy(proc_pid_fname + len - (sizeof("cmdline")-1), "fd");
319 pid_slash_progname = concat_path_file(pid, bb_basename(cmdline_buf)); /* "PID/argv0" */
We could confirm at line 319
that it just use the argv[0]
i.e. the program name without the full command line. It wouldn’t be to hard to create a patch to have the full command line (stored in the variable cmdline_buf
) reported here but we’re not gonna do it that way because we will never have a netstat
program patched on different Linux hosts.
Instead, I came up with a new bash(1) function called advanced-netstat()
that I’m using to achieve that. The function use combination of awk(1) processing to format a new column with the cmdline
of the PID extracted from procfs via /proc/${PID}/cmdline
:
advanced-netstat() {
sudo netstat -laputen|head -n 1
sudo netstat -laputen|head -n 2 | tail -1| tr -d '\n'; echo -n "Program Cmd"; echo
sudo netstat -laputen|awk '/LISTEN/{
split($9, procpid, "/")
cmdline="/proc/" procpid[1]"/cmdline"
getline procline < cmdline
trunc=substr(procline, 1, 80)
gsub("\0", " ", trunc)
print $_ trunc}'
}
It gives you the following output for a listening faked SSH connection on port ssh/22
using netcat nc(1) :
Standard output
[email protected]:/root# sudo netstat -laputen
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 0 252280 643/nc
tcp 0 0 172.17.0.2:52590 91.189.88.152:80 TIME_WAIT 0 0 -
tcp 0 0 172.17.0.2:52588 91.189.88.152:80 TIME_WAIT 0 0 -
Modified output
[email protected]:/root# advanced-netstat
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name Program Cmd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 0 254692 673/nc nc -l -p 22 -m 10 -q 2 -P sbz -w 10 -v -4
It’s quite handy if you have multiple processes with the same program name running. You could identify correctly who is who instead of trying to figure out by using multiple shell commands each time.
Alternatively, it could have been done using socket stat ss(8) program from the iproute2 Linux project when invoked with ss -l -p -t
with display options -l for listen, -p process, -t for tcp but I’m used to netstat
.