4

I'm having a discussion with a colleague: Is it better practice, or even needed, to explicitly specify the full paths to commands in a shell script (such as an install script, cronjob, etc)?

For example, it might be the case that a user of the script has setup their system (or has been hacked (in which case, arguably all bets are off)) such that an identically-named command exists elsewhere on their system and is found earlier in their command search path than the command that the script relies upon, with potentially unexpected or adverse results.

Is it worthwhile specifying full paths to ensure that the intended command is used by the script, or is this just overthinking things?

1
  • A good example of that is the script of Michael Petzl for setting up services, part of the Apache installation (it was true in 2010).
    – Sandburg
    Commented Jun 27 at 7:18

2 Answers 2

4

This is context dependent and both options have their advantages and disadvantages. On balance I would avoid using absolute paths unless you have a very specific reason to do so.

Calling using PATH environment variable

Calling commands without specifying their absolute path (IE using their existence in a PATH directory) can make a script more portable. This is perhaps less likely to be an issue for programs in /bin but definitely true for any commands you expect to be in /usr/bin. Different systems can put these in all sorts of places such as /opt or /snap.

Worse, users can configure their path for many different reasons. This may include such things as having multiple java runtimes or python versions installed. So any call to java should almost never be /usr/bin/java because they system administrator may have installed a version which is incompatible with your script. Allowing the user to choose which java version to use is vital.

Another example of this is that some distributions don't necessarily follow the conventions that you expect. In fact Archlinux has bundled /bin /sbin /usr/bin /usr/sbin all into one directory with symlinks to the others (see here). That should be backwards compatible but it demonstrates that some standards are not as ubiquitous as you may believe.

Note that tools such as sudo have specific protections for the PATH environment variable built in so it is generally safe to assume that scripts which need to be run with sudo will be secure even if you don't specify the absolute path.


Calling using absolute path

Usually you only use the absolute path when you have a very specific reason to do so.

The primary advantage of using absolute paths is that you have more control over precisely which commands are being run. This can be where you have specific alternative tools installed which are intended to override the user specified path.

You have pointed out the question of security. There are ways that this can be useful, but as noted sudo executed commands are rarely an issue.

You mention cron scripts. Famously cron has a problem with the PATH environment variable in that it is not often set as you expect (see here). I have in the past written scripts with absolute paths for use with cron. This was more because I didn't trust the sys-admin installing it. My preference would be always to run cron jobs with a well setup PATH rather than absolute paths in the script.

1

In addition to the accepted answer, I want to add another effect of using absolute paths: preventing the usage of shell built-in commands.

For instance:

  • echo: the shell will use the built-in echo command, or fallback to an available echo program in PATH.
  • /bin/echo: forces the shell to use this program, which is slightly more costly than the built-in command.

See the list of other built-in commands in Bash.

That being said, two issues regarding built-in commands:

POSIX allows shells to implement standard commands as built-ins "to increase the performance of frequently used utilities or to achieve functionality that would be more difficult in a separate environment", and while the standard expects the built-ins to be executed only if the external command is available in the search PATH, that doesn't seem to be the case in many implementations.

Also, the built-in implementations are not always conformant to the standard. For instance, POSIX encourages printf instead of echo because the latter is not very portable.

Edit: updated with useful info from ikkachu.

3
  • 1
    however, ulimit (among some others) is one that needs to be executed as a builtin, since it modifies the resource limits that are per-process and inherited to child processes. echo is POSIX too, just underdefined and with various implementations varying in their implementation of it.
    – ilkkachu
    Commented Nov 29, 2022 at 19:28
  • @ilkkachu: Why single out ulimit?  ISTM that most builtins need to be builtins: . (source), alias, bg/fg, break/continue, cd, command, declare/typeset/export, disown, enable, exec, exit, ..., and that's just a subset of A-E. Commented Mar 13 at 21:20
  • 1
    @G-ManSays'ReinstateMonica', because ulimit was mentioned in the original version of the above post, my comment was before the edit.
    – ilkkachu
    Commented Mar 14 at 7:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .