3

How can I force a specific binary to be used when executing a bash script?

I have a bash script which uses the "php" binary.

There are several php versions on my computer. The main php binary, as configured via the PATH variable, is not the one to be used in this case.

Normally the script will be executed like this:

./script.sh

I need something like this:

php=/usr/bin/php ./script.sh

NOTE: It is not an option to temporary change the PATH variable just for this command, because this will affect other dependencies.

Hardcoding it in the script is also not an option, because the script is used by multiple people. So when other people execute the script it should just use the main php binary as specified in the PATH variable.

I don't want it to be accessible via a variable. I actually want to specify the exact location to look for the binary. Just like it would normally do by using PATH, only now for one single binary with the absolute path to it. If this script calls another script, that second script also needs to use that php version. –

6
  • Can you set the PHP path inside the script, and run it in there? (ie. PHP='/usr/bin/php' PHP script.php) – BriGuy Oct 18 '13 at 14:16
  • What is php being used for? Can't you enforce a version in that script? – goldilocks Oct 18 '13 at 14:18
  • Hardcoding it in the script is also not an option, because the script is used by multiple people. So when other people execute the script it should just use the main php binary as specified in the PATH variable. – Nick Stemerdink Oct 18 '13 at 14:18
  • 1
    What's wrong with assigning the php variable before calling the script like you did? – Joseph R. Oct 18 '13 at 16:21
  • @JosephR. I don't want it to be accessible via a variable. I actually want to specify the exact location to look for the binary. Just like it would normally do by using PATH, only now for one single binary with the absolute path to it. If this script calls another script, that second script also needs to use that php version. – Nick Stemerdink Oct 18 '13 at 18:06
1

You say NOTE: It is not an option to temporary change the PATH variable just for this command, because this will affect other dependencies, but I think it is an option if you do it right.

You can create a personal directory that has only your desired php in it, and put that personal directory first in your own PATH. That personal PATH entry will affect the shell finding only that one php binary, and not affect any other PATH dependencies. Other people running the script won't use your PATH, so it won't affect them. For example:

$ mkdir -p "$HOME/myphp"
$ ln -s /usr/bin/php "$HOME/myphp/"
$ PATH=$HOME/myphp:$PATH
$ ./script.sh

The above method only affects the one php program, nothing else, and it only affects it for you, not anyone else.

Of course you can put your new PATH definition in the shell start-up file for your account so that only the commands you run will use this version of php.

5

This would work:

php() {  /path/to/your/php $@; }; export -f php; ./script.sh ; unset -f php

To break it down:

php() {  /path/to/your/php $@; }; 

Defines a shell function that will pass all of its arguments to the php path you provide.

export -f php

Exports the newly created function for use within your script

./script.sh

Executes your script

unset -f php

Removes the shell function we defined earlier.

1
  • The above doesn't work for programs that look for php in $PATH, e.g. anything that isn't a Bourne-style shell. The right answer is to put the desired php in a directory that is first in $PATH - see my Oct 19 answer. – Ian D. Allen Jan 24 '14 at 22:46
2

One way to do it would be to add an additional variable to your script:

PHP=$1
if [ -z $PHP ]; then
    PHP=php
fi

Then, if you run it without specifing anything, it will use the default PHP binary. Else, it will use the one you'll pass through your variable

./script.sh /usr/bin/php
2
$ hash /usr/local/bin php
$ php file.php

help :

$ LANG=C help hash
hash: hash [-lr] [-p pathname] [-dt] [name ...]
    Remember or display program locations.

    Determine and remember the full pathname of each command NAME.  If
    no arguments are given, information about remembered commands is displayed.

    Options:
      -d                forget the remembered location of each NAME
      -l                display in a format that may be reused as input
      -p pathname       use PATHNAME is the full pathname of NAME
      -r                forget all remembered locations
      -t                print the remembered location of each NAME, preceding
                each location with the corresponding NAME if multiple
                NAMEs are given
    Arguments:
      NAME              Each NAME is searched for in $PATH and added to the list
                of remembered commands.

    Exit Status:
    Returns success unless NAME is not found or an invalid option is given.
10
  • 1
    Awesome, this is what I need. I modified the command a little bit to make it work "hash -p /usr/bin/php php". And afterwards optionally reset it with "hash -d php". – Nick Stemerdink Oct 19 '13 at 11:49
  • @NickStemerdink Note that this has essentially the same effect as defining a function: the override is only effective when php is called by the same shell where you run hash`, not in subprocesses started from this script. – Gilles 'SO- stop being evil' Oct 20 '13 at 1:12
  • @Gilles, You are right, I noticed that (even though I find this method more convenient). Is there a way to have subprocesses using the override? – Nick Stemerdink Oct 22 '13 at 10:01
  • 1
    @Gilles, I know. But the problem is that the path to a folder should be specified, and not a absolute path to the binary. This causes other binaries in that directory to also have precedence. That's not what I want. I solved the problem now by creating a new directory for temporary overrides, and added that directory as the first one in $PATH (something like this answer: unix.stackexchange.com/a/96711/49486). – Nick Stemerdink Nov 6 '13 at 16:25
  • 1
    Now, when I need a temporary override I create a symbolic link for that binary to the "override directory", then execute the main command, and then remove the symbolic link. – Nick Stemerdink Nov 6 '13 at 16:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.