Why is my $PATH different in the executed script?
echo $PATH inside gnome terminal:
/home/pc/less.js/bin:/home/pc/local/bin:/home/pc/local/bin:/home/pc/.rvm/gems/ruby-1.9.2-head/bin:/home/pc/.rvm/gems/ruby-1.9.2-head@global/bin:/home/pc/.rvm/rubies/ruby-1.9.2-head/bin:/home/pc/.rvm/bin:/usr/local/bin:/home/pc/local/bin:/usr/lib64/mpi/gcc/openmpi/bin:/home/pc/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/games:/usr/lib64/jvm/jre/bin:/home/pc/Programming/Software/tup:/home/pc/Programming/Libraries/depottools:/home/pc/Programming/Libraries/apache-maven-3.0.4/bin
From inside this script:
#!/bin/zsh
echo $PATH
while inotifywait -e modify /home/pc/vbox-shared/less; do
lessc custom.less > /home/pc/vbox-shared/less/custom.css
done
/usr/lib64/mpi/gcc/openmpi/bin:/home/pc/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/games:/usr/lib64/jvm/jre/bin
As you can see, I modified my .zshrc
file with this:
export PATH=/home/pc/less.js/bin:$PATH
Why does it not work in the script when executed as a file? The problem is that the lessc command is not being found.
Solution 1:
The script is run using /bin/zsh
, which is not an interactive or login shell and doesn't load this file. From man zsh
, emphasis mine:
Commands are first read from /etc/zshenv; this cannot be overridden. Subsequent behaviour is modified by the RCS and GLOBAL_RCS options; the former affects all startup files, while the second only affects global startup files (those shown here with an path starting with a /). If one of the options is unset at any point, any subsequent startup file(s) of the corresponding type will not be read. It is also possible for a file in $ZDOTDIR to re-enable GLOBAL_RCS. Both RCS and GLOBAL_RCS are set by default.
Commands are then read from $ZDOTDIR/.zshenv. If the shell is a login shell, commands are read from /etc/zprofile and then $ZDOTDIR/.zprofile. Then, if the shell is interactive, commands are read from /etc/zshrc and then $ZDOTDIR/.zshrc. Finally, if the shell is a login shell, /etc/zlogin and $ZDOTDIR/.zlogin are read.
The script inherits the environment from where it's called, and if this isn't another (interactive) shell, it won't contain the preferences you set in .zshrc
.
You can set the PATH
where it applies globally (e.g. /etc/zshenv
), set it explicitly in the script directly, or change the shebang script header to run /bin/zsh -i
instead, making it load .zshrc
(quoting man zsh
: Force shell to be interactive. It is still possible to specify a script to execute.).
Alternatively, just specify the full path to the program that isn't on the default PATH
, e.g. /home/pc/less.js/bin/lessc
.
Solution 2:
zsh startup files (a.k.a. rc files)
A filename below that is not a full path is implicitly preceded by “$ZDOTDIR/”, which is typically your home directory.
The order in which zsh sources startup script files is as follows.
/etc/zshenv – First, commands are read from here; options cannot be override this.
.zshenv
/etc/zprofile – login shell
.zprofile – login shell
/etc/zshrc – interactive shell
.zshrc – interactive shell
/etc/zlogin – login shell
.zlogin – login shell
Two zsh options affect whether zsh sources certain of the above files. (“RCS” is the plural of “rc”, rendered in upper case.)
RCS and GLOBAL_RCS zsh options are set by default.
- RCS – affects all startup files
- GLOBAL_RCS – affects only global startup files (pathnames starting with “/”)
If a startup file unsets one of these options, zsh skips subsequent startup files of the that type.
If a startup file sets the GLOBAL_RCS option, zsh sources subsequent global startup files.