The $2
is within double quotes on the local shell command line, so expanded by your local shell (probably to the empty string).
So the command run on the remote host is something like:
ps -ef | grep foo | grep -v grep | awk {'print '} | xargs kill -9
That awk
command is a no-op (prints all the lines) and xargs
will eventually run:
kill -9 <all-the-words-present-in-the-output-of-ps|grep...>
That includes pid and ppid, user names...
Also if the pid of the kill command is in that list, it will kill itself and thus not be able to kill the remaining ones in the list.
Here, you'd want:
ssh foo@<IP Address> 'pkill -KILL -f foo'
(kills all processes whose command line (at least the first few kilobytes of it) contains foo
).
Or if the remote system doesn't have a pkill
command:
ssh foo@<IP Address> '
ps -Ao pid= -o args= |
awk "/[f]oo/ {print \$1}" |
xargs kill -s KILL'
We use single quotes on the local side (so no variable expansion there), and double quote for the awk code in the remote shell command line, so we need to escape the $
in $1
so that it is not expanded by the remote shell.
awk
is a superset of grep
, you generally don't need to pipe them together. Best is to tell ps
to output only the things you want to match on, here assuming you want to search for foo
in the list of arguments displayed by ps as your usage of -f
suggests.
If you want to kill all processes of the remote user (here of user foo and sshing as foo), you could do:
ssh foo@<IP Address> 'kill -s KILL -- -1'
That will kill all the processes that the user has permission to kill. For a normal user, that's all processes whose real or saved set user id is the same as the real or effective user id of the killing process.
Or:
ssh foo@<IP Address> 'pkill -KILL -U "$(id -u)"'
(or pkill -U foo
). To kill all processes whose real user id is the same as the effective user id of the remote user.
Or you could do:
ssh foo@<IP Address> '
trap "" HUP
ps -Ao sid= -o pid= -U "$(id -u)" |
awk "\$1 != $(ps -eo sid= -p "\$\$") {print \$2}" |
xargs kill -s KILL'
(checking on sid
so that kill
doesn't kill itself, the shell, awk
or xargs
, and ignoring SIGHUP in case killing the user sshd
process causes that signal to be sent)
We're assuming the login shell of the remote user is Bourne-like. Those commands would have to be adapted if the login shell of the remote user is of the csh or rc families which have a different syntax for instance.
It's also better practice to refer to signals by their name rather than number as that makes it clearer and the signal number can change from system to system (9 for SIGKILL is quite universal though).
Best Answer
Of course the one liner you wrote won't work since the $1 is inside the quotes. Try this:
Have fun but use it with caution. I generally don't like system commands in gawk, certainly not the "kill" command.