简体   繁体   English

在脚本中运行时,su -c命令失败

[英]su -c command fails when running in a script

I am trying to issue a unicorn command via a shell script on a digital ocean ubuntu server. 我正在尝试通过数字海洋Ubuntu服务器上的Shell脚本发出独角兽命令。 The command is: 该命令是:

su - xxx -c cd /home/xxx/apps/app_name && rbenv rehash && rbenv local 2.3.1 && /home/xxx/apps/app_name/bin/unicorn -c /home/xxx/apps/app_name/config/unicorn.rb -E production -D

This command works when issued on the command line but if I put it into a script like this: 该命令在命令行上发布时有效,但是如果我将其放入如下脚本中:

#!/bin/sh

USER=xxx

APP_ROOT=/home/xxx/apps/app_name
RBENV_RUBY_VERSION=2.3.1

SET_PATH="cd $APP_ROOT && rbenv rehash && rbenv local $RBENV_RUBY_VERSION"
RAILS_ENV=production
UNICORN="$APP_ROOT/bin/unicorn"
UNICORN_OPTS="-c $APP_ROOT/config/unicorn.rb -E $RAILS_ENV -D"
CMD="$SET_PATH && $UNICORN $UNICORN_OPTS"

su - $USER -c "$CMD"

I get this error: -su: rbenv: command not found 我收到此错误: -su: rbenv: command not found

If I remove the quotes around $CMD , I get this error: su: invalid option -- 'E' 如果删除$CMD周围的引号, $CMD此错误: su: invalid option -- 'E'

Does anyone know how to get around this problem? 有谁知道如何解决这个问题?

Following the comments below, I have amended the script by adding a path to rbenv like this: 按照下面的评论,我通过添加如下所示的rbenv路径来修改了脚本:

RBENV_ROOT="/home/$USER/.rbenv"
SET_PATH="cd $APP_ROOT && $RBENV_ROOT/bin/rbenv rehash && $RBENV_ROOT/bin/rbenv local $RBENV_RUBY_VERSION"

When I run this now I get the following error: -su: cd /home/xxx/apps/app_name && /home/xxx/.rbenv/bin/rbenv rehash && /home/xxx/.rbenv/bin/rbenv local 2.3.1 && /home/xxx/apps/app_name/bin/unicorn /home/xxx/apps/app_name/config/unicorn.rb -E production -D: No such file or directory 当我现在运行此命令时,出现以下错误: -su: cd /home/xxx/apps/app_name && /home/xxx/.rbenv/bin/rbenv rehash && /home/xxx/.rbenv/bin/rbenv local 2.3.1 && /home/xxx/apps/app_name/bin/unicorn /home/xxx/apps/app_name/config/unicorn.rb -E production -D: No such file or directory

The reason you get different results, is that the shell splits the command is actually split into multiply parts: 得到不同结果的原因是,shell拆分了命令,实际上将其拆分为多个部分:

su - xxx -c cd /home/xxx/apps/app_name 
&& rbenv rehash
&& rbenv local 2.3.1 
&& /home/xxx/apps/app_name/bin/unicorn -c /home/xxx/apps/app_name/config/unicorn.rb -E production -D

For each newline a new command is called in your shell (As your user, not the substituted). 对于每一个新行新的命令被称为在壳(如用户 ,而不是取代)。

The above means call su with '-' 'xxx' '-c' 'cd' '/home/xxx/apps/app_name' , if that success then call rbenv with 'rehash' , and so on... 上述方法调用su'-' 'xxx' '-c' 'cd' '/home/xxx/apps/app_name' ,如果成功,则调用rbenv'rehash' ,等等...

And in your script all of these are interpreted as one arguments: 在您的脚本中,所有这些都被解释为一个参数:

# Terminal:
su - user -c ls && echo 1
# Script
su - user -c 'ls && echo 1'

When all of this is said, it should be clear that your script is doing what it should do, but that rbenv is not in the $PATH set inside su . 说完所有这些后,应该清楚您的脚本正在执行应做的事情,但是rbenv不在su内的$PATH You can get around this by using the absolute path to rbenv : 您可以通过使用rbenv的绝对路径来解决此rbenv

su - xxx -c 'cd /home/xxx/apps/app_name && /path/to/rbenv ...'

A few things to note: Uppercase variable names are reserved to environment variables , so you should consider using lowercase names. 需要注意的几件事:大写变量名称保留给环境变量使用 ,因此您应该考虑使用小写名称。 When you don't wrap parameter expansions in double quotes they will undergo word splitting and globbing . 当您不将参数扩展用双引号引起来时,它们将经历单词拆分遍历

In your case the su command is applied only to the cd command. 在您的情况下, su命令仅适用于cd命令。

Shell will split your command to following commands and evaluate each of them separately and use their return code to (partially) evaluate the && expression: Shell会将您的命令拆分为以下命令,并分别评估每个命令,并使用其返回码(部分)评估&&表达式:

su - xxx -c cd /home/xxx/apps/app_name
rbenv rehash
rbenv local 2.3.1
/home/xxx/apps/app_name/bin/unicorn -c /home/xxx/apps/app_name/config/unicorn.rb -E production -D

So when we draw an evaluation tree, it will look like this: 因此,当我们绘制评估树时,它将如下所示:

shell
 `-- &&
     |-- su
     |   `-- shell
     |       `-- cd
     |-- rbenv
     |-- rbenv
     `-- unicorn

So to apply su to whole thing (as you want) wrap it in the quotes: 因此,将su应用于整个事物(根据需要),将其用引号引起来:

su - xxx -c 'cd /home... && rbenv ... && ...'

So when we draw an evaluation tree of the fixed command, it will look like this: 因此,当我们绘制固定命令的评估树时,它将如下所示:

shell
 `-- su
     `-- shell
         `-- &&
             |-- cd
             |-- rbenv
             |-- rbenv
             `-- unicorn

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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