[英]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.