简体   繁体   中英

Syntax errors when executing a complex command via ssh

I would like to know if a server is running and if not then i would like to start it. for this scenario I have written the following bash script

ssh -t machine "cd /to/the/bin/path 
  && if [ -n $(sudo -u dev ps U dev | grep server_name | awk 'FNR == 1 {print $1}') ] 
     then 
          echo 'podsvr is running with 
             id $(sudo -u dev ps U dev | grep POD | awk 'FNR == 1 {print $1}')' 
     else 
          sudo -u dev sfservice server_name start 
     fi
"

When I run the above program I am getting the following error

bash: -c: line 1: syntax error: unexpected end of file

Could some one please help me in this regards

~Sunil

You can't nest single quotes like that in bash. Change the second occurrence of:

 'FNR == 1 {print $1}'

To:

'\''FNR == 1 {print $1}'\''

Your quoting is messed up. Probably the main problem is that you put the entire ssh script in double quotes. Since it's included in double quotes, the $(...) parts are already evaluated on the local machine before the result is passed to the remote one, and the results are fairly nonsensical. I would use the following recipe:

  1. Write the script that should be executed on the remote machine. Preferably log in to the remote machine and test it there.

  2. Now enclose the entire script in single quotes and replace every enclosed ' by '\\'' or alternatively by '"'"' .

  3. In case that the command contains a variable that should be evaluated on the local machine, put '\\'" in front of it and "\\'' after it. For instance, if the command to be executed on the remote machine is

     foo "$A" "$B" 'some string' bar 

    but $B should be evaluated on the local machine, you get

     'foo "$A" '\\'"$B"\\'' '\\''some string'\\'' bar' 

    3.1 Note: This is not completely foolproof – it will fail if the string in $B contains ' . To be safe in cases where you cannot guarantee that there is no ' inside of $B , you can first execute QQ=\\'\\\\\\'\\' ; ProtectedB=${B//\\'/$QQ} QQ=\\'\\\\\\'\\' ; ProtectedB=${B//\\'/$QQ} and then use '\\'"$ProtectedB"\\'' instead of '\\'"$B"\\'' in the command above.

  4. Use the result as the argument of ssh.

I assume that the following works (but I can't test it here).

ssh -t machine '
    cd /to/the/bin/path
    && if [ -n "$(sudo -u dev ps U dev | grep server_name | awk '\''FNR == 1 {print $1}'\'')" ]
       then
           echo "podsvr is running with id $(sudo -u dev ps U dev | grep POD | awk '\''FNR == 1 {print $1}'\'')"
       else
           sudo -u dev sfservice server_name start
       fi
'

There are a few things you can do to improve the command and simplify the quoting:

  1. There's no need to run ps using sudo to see processes running as another user.
  2. Use the -q option to suppress the output of grep , and simply check the exit status to see if a match was found.
  3. Use double-quotes with echo to allow the svc_id parameter to expand.
  4. Use single quotes around the entire command for the argument to ssh .
  5. Presumably, /to/the/bin/path is where sfservice lives? You can probably just specify the full path to run the command, rather than changing the working directory.

ssh -t machine 'if ps U dev -o command | grep -q -m1 server_name; then
                  svc_pid=$( ps U dev -o pid,command | grep -m1 POD | cut -d" " -f 1 )
                  echo "podsvr is running with id $svc_pid"
                else 
                  sudo -u dev /to/the/bin/path/sfservice server_name start 
                fi
'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM