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).
pkill foo
. Otherwise, tryxargs echo kill
to help see whatxargs
is running. – thrig Mar 8 '16 at 23:31ssh foo@<IP Address> "ps -ef | grep foo | grep -v grep | awk {'print $2'} | xargs /bin/echo kill -9"
an we will see how your kill argument look like – MAQ Mar 8 '16 at 23:46$2
as\$2
- it's inside double-quotes so will be expanded by your local shell...probably empty so theawk
command is actuallyawk '{print }'
. or just usepkill
orpgrep
as others have recommended, if they are available. – cas Mar 8 '16 at 23:46grep '[f]oo'
and you don't need the| grep -v grep
. – Kevin Mar 9 '16 at 0:22