Answering your question literally, here's one way to list the last PID displayed by lsof
:
lsof … | awk 'END {print $2}'
Awk is a text processing language which reads input and processes it line by line. In the code, END {…}
executes the code in the braces after the whole input is processed, and effectively operates on the last line. $2
is the second whitespace-delimited field on the line.
And here are some ways to kill it (each line works on its own):
kill $(lsof … | awk 'END {print $2}') lsof … | awk 'END {print $2}' | xargs kill lsof … | awk 'END {system("kill " $2)}'
However, I dispute your assertion that the right process to kill is always the last one. lsof
displays processes by increasing PID, which is meaningless. Even on systems where process IDs are assigned sequentially (which is not the case on all Unix variants, not even on all Linux installations), they wrap once they reach the maximum value (commonly 32767). Thus deciding between processes by comparing PIDs is meaningless.
You need some other information to decide which process to kill. Depending on what kind of information you're after and on whether you might have output that contains “weird” characters (like spaces in file or program names), you may use a tool like awk to process the output of lsof
, or you may use the -F
option to lsof
which produces output that's a bit harder to parse in simple cases but (almost) not prone to ambiguity and easier to parse robustly. For example, if you want to kill any process that's listening on port 8080, here's how you can do it:
lsof -n -i :8080 -F | awk ' sub(/^p/,"") {pid = $0} $0 == "n*:http-alt" {print pid} ' | xargs kill
The call to the sub
function replaces p
at the beginning of a line by an empty string. If this replacement is performed, the code block {pid = $0}
is executed; this way the pid
variable contains the last PID value displayed by lsof
. The second awk line prints the value of the pid
variable if the line is exactly "n*:http-alt"
, which is lsof's way to report a socket listening on port 8080 on all interfaces.
This particular criterion actually doesn't require any parsing (I only showed it above as an example). You can make lsof
display just processes listening on the specified port:
lsof -n -a -iTCP:8080 -sTCP:LISTEN -Fp | sed 's/^p//' | xargs kill
Or, for this, you can use netstat
instead.
netstat -lnpt | awk '$4 ~ /:8080$/ {sub(/\/.*/, "", $7); print $7}'
Explanation of the awk code: if the 4th column ends with :8080
, replace everything after the first /
in the 7th column (to remove the process name part and keep only the PID part), and print it.