通过ssh执行复杂命令时出现语法错误

时间:2013-05-17 05:35:31

标签: bash ssh

我想知道服务器是否正在运行,如果没有,那么我想启动它。对于这种情况,我编写了以下bash脚本

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
"

当我运行上述程序时,我收到以下错误

  

bash:-c:第1行:语法错误:意外的文件结尾

有人可以在这方面帮助我

〜苏尼

3 个答案:

答案 0 :(得分:2)

你不能在bash中嵌套这样的单引号。更改第二次出现:

 'FNR == 1 {print $1}'

要:

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

答案 1 :(得分:1)

你的报价搞砸了。可能主要的问题是你把整个ssh脚本放在双引号中。由于它包含在双引号中,因此在将结果传递给远程引号之前,已在本地计算机上评估$(...)部分,结果相当荒谬。我会使用以下食谱:

  1. 编写应在远程计算机上执行的脚本。最好登录远程机器并在那里进行测试。

  2. 现在将整个脚本包含在引号中,并将{strong>每个括起'替换为'\'',或者替换为{{1} }。

  3. 如果该命令包含应在本地计算机上评估的变量,请将'"'"'放在其前面,然后将'\'"放在其后面。例如,如果要在远程计算机上执行的命令是

    "\''

    但应在本地计算机上评估foo "$A" "$B" 'some string' bar

    $B

    3.1 注意:这并非完全万无一失 - 如果'foo "$A" '\'"$B"\'' '\''some string'\'' bar' 中的字符串包含$B,则会失败。为了确保您无法保证'内没有',您可以先执行$B,然后使用QQ=\'\\\'\' ; ProtectedB=${B//\'/$QQ}代替'\'"$ProtectedB"\''在上面的命令中。

  4. 使用结果作为ssh的参数。

  5. 我认为以下工作(但我不能在这里测试)。

    '\'"$B"\''

答案 2 :(得分:1)

您可以采取一些措施来改进命令并简化引用:

  1. 无需使用ps运行sudo即可查看以其他用户身份运行的进程。
  2. 使用-q选项取消grep的输出,只需检查退出状态即可 查看是否找到了匹配项。
  3. echo处使用双引号以允许svc_id参数展开。
  4. 在整个命令周围使用单引号作为ssh的参数。
  5. 据推测,/to/the/bin/pathsfservice生活的地方?您可以只指定运行命令的完整路径,而不是更改工作目录。

  6. 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
    '