PEAR not recognising correct PHP directory

Viewed 346

I just installed PEAR but it is using an incorrect path for PHP, /usr/bin/php, rather than the correct one, /usr/bin/php74.

This means it won't run at all, so I can't even run pear uninstall pear, because it (like any other pear command) just errors out with /usr/bin/pear line 28: /usr/bin/php: No such file or directory

How do I fix this? Can I just rm -rf /usr/bin/pear and then reinstall with pacman?

(For reference I am using Arch Linux)

1 Answers

I was curious about this so I took a bit of fun time to play with pear.

So, first I installed it through my favorite - and not deprecated yet - AUR helper.

$ my-awesome-helper -S php-pear

Then I tried to install XML_Util (as an example)

# pear install XML_Util
WARNING: channel "pear.php.net" has updated its protocols, use "pear channel-update pear.php.net" to update
downloading XML_Util-1.4.5.tgz ...
Starting to download XML_Util-1.4.5.tgz (19,191 bytes)
......done: 19,191 bytes
install ok: channel://pear.php.net/XML_Util-1.4.5

# echo $?
0

From here, I was sure that it is working so I uninstalled it.

# pear uninstall XML_Util
uninstall ok: channel://pear.php.net/XML_Util-1.4.5

Now, how can we break it or change the location of the PHP binary? The way to go is to follow the documentation. For our case, it is located here.

It first states:

PEAR has a number of configuration options that you can change. Getting an overview of them is as easy as issuing a

$ pear config-show

I did it a bit more precisely:

# pear config-show | grep bin
PEAR executables directory     bin_dir          /usr/bin
PHP CLI/CGI binary             php_bin          /usr/bin/php
Signature Handling Program     sig_bin          /usr/bin/gpg

Yet another question: How to change the value of php_bin?

Let's get back to the documentation. It now states:

Reading single values is accomplished by using config-get. The following command will show you where all the .php files of your installed pear packages reside.

$ pear config-get php_dir
/usr/share/pear

Changing a value is as easy as retrieving it:

$ pear config-set preferred_state beta
config-set succeeded

Therefore, I changed it to something that is not the PHP binary.

# pear config-set php_bin /tmp/my-awesome-bin
config-set succeeded

Let's check the change:

# pear config-get php_bin
/tmp/my-awesome-bin

We are now sure that we changed the PHP binary location.

Let's rerun our first command:

# pear install XML_Util
WARNING: channel "pear.php.net" has updated its protocols, use "pear channel-update pear.php.net" to update
downloading XML_Util-1.4.5.tgz ...
Starting to download XML_Util-1.4.5.tgz (19,191 bytes)
......done: 19,191 bytes
install ok: channel://pear.php.net/XML_Util-1.4.5

It's not broken. Weird !?

From here, I thought, I did something wrong so I rechecked everything I did and I indeed followed the documentation without success.


My last resort is always to look at the file or executable to try to understand its behavior. So I did this time too.

It turns out that pear is a simple Shell script. At the time I'm writing this it (/usr/bin/pear) looks like this:

#!/bin/sh

# first find which PHP binary to use
if test "x$PHP_PEAR_PHP_BIN" != "x"; then
  PHP="$PHP_PEAR_PHP_BIN"
else
  if test "/usr/bin/php" = '@'php_bin'@'; then
    PHP=php
  else
    PHP="/usr/bin/php"
  fi
fi

# then look for the right pear include dir
if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then
  INCDIR=$PHP_PEAR_INSTALL_DIR
  INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR"
else
  if test "/usr/share/pear" = '@'php_dir'@'; then
    INCDIR=`dirname $0`
    INCARG=""
  else
    INCDIR="/usr/share/pear"
    INCARG="-d include_path=/usr/share/pear"
  fi
fi

exec $PHP -C -q $INCARG -d date.timezone=UTC -d output_buffering=1 -d variables_order=EGPCS -d open_basedir="" -d safe_mode=0 -d register_argc_argv="On" -d auto_prepend_file="" -d auto_append_file="" $INCDIR/pearcmd.php "$@"

Here is the relevant part regarding your question:

if test "x$PHP_PEAR_PHP_BIN" != "x"; then
  PHP="$PHP_PEAR_PHP_BIN"
else
  if test "/usr/bin/php" = '@'php_bin'@'; then
    PHP=php
  else
    PHP="/usr/bin/php"
  fi
fi

Basically:

  1. If the PHP_PEAR_PHP_BIN environment variable is declared. Use it.
  2. Otherwise, if the php_bin variable (pear config) is set, and is equal to /usr/bin/php use php as executable.
  3. If both (1) and (2) failed; use the /usr/bin/php binary as executable.

That explains a lot about why it is still working.

So, I tried again to break it again but this time with the PHP_PEAR_PHP_BIN environment variable.

# PHP_PEAR_PHP_BIN=/tmp/my-awesome-bin pear install XML_Util
/usr/bin/pear: Zeile 28: /tmp/my-awesome-bin: Datei oder Verzeichnis nicht gefunden

This time I have the same error like the one you posted. Meaning that I could break pear and reproduce your issue.


Now the solution-s to your problem after understanding what is happening:

  1. You can manually run export PHP_PEAR_PHP_BIN=/usr/bin/php74 before running pear. This solution is temporary and user-wide.

  2. You can put the export PHP_PEAR_PHP_BIN=/usr/bin/php74 line into your ~/.bashrc file. This solution is persistent and user-wide.

  3. You can put the PHP_PEAR_PHP_BIN=/usr/bin/php74 line into your /etc/environment file. This solution is persistent and system-wide.

  4. You can put the export PHP_PEAR_PHP_BIN=/usr/bin/php74 line into /etc/profile.d/my_php_pear_solution.sh file. This solution is persistent and system-wide.

  5. You can create a /usr/local/bin/my-pear (assuming that /usr/local/bin is in your $PATH) which handles this; given it one of - or all - the 3 executable bit and finally use the my-pear CLI instead of the official pear one. This solution is persistent and system-wide.

    #!/usr/bin/env bash
    
    # Set the location of our PHP binary.
    export PHP_PEAR_PHP_BIN=/usr/bin/php74
    
    # Start pear.
    /usr/bin/pear ${@}
    

All of those may work. It's just a matter of scope, usability, and permission - somehow.

I hope this helps. Don't be afraid to ask if something is not clear.

P.S.: Welcome around here :-)

Related