I'm retrieving a list of two PIDs that I want to kill. My pipeline looks something likeps -ef | grep foo | grep -v grep | awk {'print $2'} | xargs kill -9Both processes are killed when executing this locally. But when using it with ssh likessh foo@<IP Address> ps -ef | grep foo | grep -v grep | awk {'print $2'} | xargs kill -9only one PID out of two is getting deleted. It outputs kill: <PID>: No such process. Could it be trying to kill the second process locally?
Passing a list of two PIDs to xargs only kills the first using ssh
shell;ssh;awk;quoting;xargs
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 -9That 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 -eo 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 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 -eo 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).