1

In a bash script that has plenty of commands run as another user, I've found a class of commands that don't seem to work.

In a Rails repository as root:

> 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)

With all kinds of Rails-oriented commands such as rails [something], rake [something], etc., the command only works if I'm literally logged in as at.

What's happening here?

sscirrus
  • 475
  • 1
  • 6
  • 10

1 Answers1

1

This seems like a $PATH or environment issue. When you run these commands via su, you're running them in another user's environment context. To confirm try doing a su -c 'echo $PATH' at, and compare that with your $PATH when you're logged in as the user at.

Shells, such as Bash, have 2 ways in which they source their config files... typically. For bash there's 2 $HOME/.bashrc and $HOME/.bash_profile that are often times the ones in play. These 2 methods for sourcing configurations are called interactive and non-interactive and are discussed in the Bash man bash page in the INVOCATION section.

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.
slm
  • 363,520
  • 117
  • 767
  • 871
  • I checked $PATH as both users and they are almost completely different (and missing what I think are some relevant entries). I read what you included in your answer, but I don't know how to fix the problem! – sscirrus Jun 29 '18 at 23:05
  • @sscirrus - look in the 2 files in the `at` user's `/home/at` directory for these 2 files and you'll likely see the PATH as it's showing up there. If not you can amend the `PATH=...` to include the additional directories that you need to get your `rake` commands working. – slm Jun 30 '18 at 00:09