4

the following command looks properly quoted and escaped:

$  echo -e ssh -q rmthost 'bash -c "ps -ef|grep '\'''\\\<'defunct'\\\>''\''|grep -v grep|awk '\'''{print \$1}''\'' "'
ssh -q sbpsvrwm757 bash -c "ps -ef|grep '\<defunct\>'|grep -v grep|awk '{print $1}' "

but when executed, the result is not what is expected:

$   ssh -q rmthost 'bash -c "ps -ef|grep '\'''\\\<'defunct'\\\>''\''|grep -v grep|awk '\'''{print \$1}''\'' "'
    root16986 16982   0        - ?           0:01 <defunct>

the awk command didn't seem to extract the right column.

Now I followed the link provided by Siguza and came up with:

$  echo ssh -q rmthost "'"bash -c '"ps -ef|grep '"'\<defunct\>'|grep -v grep|awk '{print \$1}'"'"'"'"
ssh -q rmthost 'bash -c "ps -ef|grep '\<defunct\>'|grep -v grep|awk '{print $1}'"'

that looks perfectly escaped too, but still doesn't work:

$  ssh -q rmthost  "'"bash -c '"ps -ef|grep '"'\<defunct\>'|grep -v grep|awk '{print \$1}'"'"'"'"
Missing }

or,

$  echo ssh -q rmthost  bash -c '"ps -ef|grep '"'\<defunct\>'|grep -v grep|awk '{print \$1}'"'"'
ssh -q rmthost  bash -c "ps -ef|grep '\<defunct\>'|grep -v grep|awk '{print $1}'"
$  ssh -q rmthost  bash -c '"ps -ef|grep '"'\<defunct\>'|grep -v grep|awk '{print \$1}'"'"'
   root 16986 16982   0        - ?           0:01 <defunct>

or,

$  echo ssh -q rmthost  "bash -c \"ps -ef |grep '\<defunct\>'|grep -v grep| awk '{print \$1}'\""
ssh -q rmthost  bash -c "ps -ef |grep '\<defunct\>'|grep -v grep| awk '{print $1}'"
$  ssh -q rmthost  "bash -c \"ps -ef |grep '\<defunct\>'|grep -v grep| awk '{print \$1}'\""
  root 16986 16982   0        - ?           0:01 <defunct>

any idea why?

Please note that I need bash -c to enable bash-style output redirection like >/var/tmp/1.ouy 2>&1 for the command.

your help is appreciated.

techie11
  • 1,243
  • 15
  • 30
  • Thanks. I follow that rule but still can't make it work. see the update above – techie11 Apr 30 '16 at 12:57
  • Whats wrong with `ssh rmthost "ps -ef |grep \"\\"|grep -v grep| awk '{print \$1}' " ` - or am I missing something here? i.e. by wrapping the argument to ssh in double quotes you avoid all the awkwardness. – Niall Cosgrove Apr 30 '16 at 13:35
  • Also `bash -c` is redundant here. ssh will send the command string to a shell itself saving you a whole level of escaping. – Niall Cosgrove Apr 30 '16 at 13:43
  • I forgot to mention that I need bash -c to enable bash-style output redirection > /var/tmp/1.out 2>&1. the login shell for the user is csh on the rmthost – techie11 Apr 30 '16 at 13:46
  • 1
    I would STRONGLY recommend learning about awk to avoid excessive ` `grep | grep | awk`. `awk` can do all of that for you. – Philip Couling Apr 30 '16 at 14:04
  • @couling while you are of course correct, you comment fails to address the actual question. – Niall Cosgrove Apr 30 '16 at 14:27
  • @user6170930 that's why it's a comment not an answer. Welcome to stack overflow. – Philip Couling Apr 30 '16 at 14:47
  • So the proper solution is `ssh -q rmthost "ps -ef | awk '// { print \$2 }'"` – tripleee May 02 '16 at 13:14

2 Answers2

1

I'll be honest I can't read the code you've written. It's too obfuscated and I dont have half an hour to figure it out. To that end it's most likely not good code.

Quotes like this get really very confusing when you try to understand the multiple layers of decoding. So instead of trying to correct your quotes I'm going to try to provde cleaner code with the same result.

ssh rmthost "bash -c \"ps -ef | grep '<defunct>' | grep -v grep | awk '{print \\\$2}'\""

# The remote system will execute this:
bash -c "ps -ef | grep '<defunct>' | grep -v grep | awk '{print \$2}'"

# Which in tells bash to execute this:

ps -ef | grep '<defunct>' | grep -v grep | awk '{print $2}'

However why not try to remove some exessive grep pipes. awk can do the filtering for you. I'm assuming that <defunct> appears at the end of the line. If so then you can just use:

ssh rmthost "bash -c \"ps -ef | awk '/<defunct>\\\$/ {print \\\$2}'\""

# the remote system executes this:
bash -c "ps -ef | awk '/<defunct>\$/ {print \$2}'"

# bash executes this:
ps -ef | awk '/<defunct>$/ {print $2}'

Or better still, use the second column in a ps -el which will be Z for zombie processes:

ssh rmthost "bash -c \"ps -el | awk '/^. Z / {print \\\$4}'\""

# the remote system executes this
bash -c "ps -el | awk '/^. Z / {print \$4}'"

# bash executes this:
ps -el | awk '/^. Z / {print $4}'
Philip Couling
  • 13,581
  • 5
  • 53
  • 85
  • I got "Variable syntax" error for the first command and "awk: syntax error near line 1 awk: illegal statement near line 1 " for the second command. – techie11 Apr 30 '16 at 15:05
  • Thats very strange, it works fine on my system. I've edited in the flattened examples. I'd suggest loggin into the remote system and checking that they work first. This is very simplistic `awk` syntax so I don't believe anything is going wrong with awk, but it sounds like something screwy is happening with flattening the quotes out. – Philip Couling Apr 30 '16 at 18:57
0

Here is a working solution by playing with the quotes:

ssh -q rmthost "bash -c 'ps -ef|grep ''''\<'defunct'\>''''|grep -v grep|awk "'"{print \$2}"'" '"

however, I myself don't quite understand the mechanism :-). and it does't work if you swap single and double quotes.

techie11
  • 1,243
  • 15
  • 30