采用非 sudo 用户的脚本无法找到该用户可用的命令

采用非 sudo 用户的脚本无法找到该用户可用的命令

在我的服务器上,我有一个由 sudo 用户运行的脚本。它包含以下几行:

sudo -u nonsudoer -H bash -l << HERE
echo -n "Execute code as user "; whoami
cd bundle/programs/server
echo -n "Install package at "; pwd
npm install --production
HERE

这些行产生以下输出:

Execute code as user nonsudoer
Install package at /var/www/example/bundle/programs/server
bash: line 4: npm: command not found

但是,当我手动运行这些行时......

$ sudo -u nonsudoer -H bash -l
manpath: can't set the locale; make sure $LC_* and $LANG are correct
$ echo -n "Execute code as user "; whoami
Execute code as user nonsudoer
$ cd bundle/programs/server
$ echo -n "Install package at "; pwd
Install package at /var/www/example/bundle/programs/server
$ npm install --production
  <command successful; output clipped>
$ exit

... 一切按预期进行。我的脚本中哪里做错了?

答案1

当你调用bash -lshell 并在命令行上与其交互时,新的 bash 登录 shell 是交互的,您可以通过检查特殊参数的值来确认$-

steeldriver@machine:~$ sudo -u testuser -H bash -l
testuser@machine:/home/steeldriver$ echo $-
himBHs
testuser@machine:/home/steeldriver$ exit
logout

当你bash -l通过此处文档调用时,你会得到一个非交互式登录外壳:

steeldriver@machine:~$ sudo -u testuser -H bash -l << HERE
echo \$-
HERE
hBs
steeldriver@machine:~$

(请注意,我进行了转义,$-以防止它被交互式父shell扩展)。

根据man bash,bash 登录 shell 使用 进行初始化~/.profile~/.bash_profile如果存在),而非登录 shell 使用 进行初始化。Ubuntu 通过有条件地从 进行~/.bashrc获取,让情况变得有些混乱。但是 rc 文件内置了交互性检查:~/.bashrc~/.profile

$ sudo -u testuser -H head /home/testuser/.bashrc
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

因此,在非交互式情况下,~/.bashrc几乎立即终止,绕过PATH您稍后在文件中添加的任何规范,而在交互式情况下,您的全部内容~/.bashrc都会被处理(尽管处于登录 shell 中),并且您的 npmPATH可能会被添加到那里。

相关内容