在具有大量以其他用户身份运行的命令的 bash 脚本中,我发现一类命令似乎不起作用。
以 root 身份在 Rails 存储库中:
> su -c 'whoami' at
at
> su -c 'rake tmp:clear' at
rake aborted!
LoadError: cannot load such file -- bundler/setup
> login at
> rake tmp:clear
(Success)
对于各种面向 Rails 的命令,例如rails [something]
、rake [something]
等,该命令仅在我实际登录为 at 时才有效。
这里发生了什么事?
答案1
这似乎是一个$PATH
环境问题。当您通过 运行这些命令时su
,您是在另一个用户的环境上下文中运行它们。要确认,请尝试执行 a su -c 'echo $PATH' at
,并将其与您$PATH
以用户身份登录时的结果进行比较at
。
Shell(例如 Bash)有两种获取配置文件的方式……通常是这样。对于 bash 有 2 个$HOME/.bashrc
,$HOME/.bash_profile
这通常是正在运行的那些。这两种获取配置的方法称为交互式和非交互式,并在 Bashman bash
页面的调用部分中进行了讨论。
INVOCATION
A login shell is one whose first character of argument zero is a -, or
one started with the --login option.
An interactive shell is one started without non-option arguments and
without the -c option whose standard input and error are both connected to
terminals (as determined by isatty(3)), or one started with the -i option. PS1
is set and $- includes i if bash is interactive, allowing a shell script or a
startup file to test this state.
The following paragraphs describe how bash executes its startup files.
If any of the files exist but cannot be read, bash reports an error. Tildes are
expanded in file names as described below under Tilde Expansion in the
EXPANSION section.
When bash is invoked as an interactive login shell, or as a
non-interactive shell with the --login option, it first reads and executes
commands from the file /etc/profile, if that file exists. After read‐ ing that
file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that
order, and reads and executes commands from the first one that exists and is
readable. The --noprofile option may be used when the shell is started to
inhibit this behavior.
When a login shell exits, bash reads and executes commands from the files
~/.bash_logout and /etc/bash.bash_logout, if the files exists.
When an interactive shell that is not a login shell is started, bash
reads and executes commands from ~/.bashrc, if that file exists. This may be
inhibited by using the --norc option. The --rcfile file option will force bash
to read and execute commands from file instead of ~/.bashrc.
When bash is started non-interactively, to run a shell script, for
example, it looks for the variable BASH_ENV in the environment, expands its
value if it appears there, and uses the expanded value as the name of a file to
read and execute. Bash behaves as if the following command were executed: if [
-n "$BASH_ENV" ]; then . "$BASH_ENV"; fi but the value of the PATH variable is
not used to search for the file name.