On a test install I updated drush and all aegir components to HEAD.

Following this all Aegir tasks failed, with the error:

Unable to automatically determine the path to the PHP interpreter. Please supply the --php argument.

An example command was:

Running: /var/aegir/drush/drush.php --root='/var/aegir/platforms/atrium-1-0-beta3' 'provision' 'disable' 'site.example.com' --backend

However, it does seem to go through all the remaining steps okay. Here's the full log:

Task starts processing
Unable to automatically determine the path to the PHP interpreter. Please supply the --php argument.
Running: /var/aegir/drush/drush.php --root='/var/aegir/platforms/atrium-1-0-beta3' 'provision' 'disable' 'site.example.com' --backend
Drush bootstrap phase : _drush_bootstrap_drush()
opendir(/var/aegir/.drush/provision/provision.tmp): failed to open dir: Permission denied
Drush bootstrap phase : _drush_bootstrap_drupal_root()
Loading drushrc "/var/aegir/platforms/atrium-1-0-beta3/drushrc.php" into "drupal" scope.
Initialized Drupal 6.14 root directory at /var/aegir/platforms/atrium-1-0-beta3
Found command: provision disable
Initializing drush commandfile: provision_apache
Undefined index: base_url
Initializing drush commandfile: provision_drupal
Initializing drush commandfile: provision_mysql
Undefined index: db_url
Including /var/aegir/.drush/provision/web_server/disable.provision.inc
Including /var/aegir/.drush/provision/platform/disable.provision.inc
Including /var/aegir/.drush/provision/platform/backup.provision.inc
Including /var/aegir/.drush/provision/db_server/backup.provision.inc
Drush bootstrap phase : _drush_bootstrap_drupal_site()
Initialized Drupal site adam.pilotinternet.com at sites/site.example.com
Loading drushrc "/var/aegir/platforms/atrium-1-0-beta3/sites/site.example.com/drushrc.php" into "site" scope.
Generating mysql dump for adam.pilotinternet.com.
mysqldump --defaults-file=/dev/fd/3 -rsites/site.example.com/database.sql adampilotinter
Adding sites directory to /var/aegir/backups/site.example.com-2009-09-24.tar
tar -C /var/aegir/platforms/atrium-1-0-beta3/sites/site.example.com -p -c -f /var/aegir/backups/site.example.com-2009-09-24.tar .
gzip /var/aegir/backups/site.example.com-2009-09-24.tar
Deleted mysql dump from sites directory
Generating apache host configuration file site.example.com_80.
Apache has been restarted
Drushrc file (sites/site.example.com/drushrc.php) was written successfully
Command dispatch complete
Removing task from hosting queue
An error occurred at function : drush_hosting_hosting_task
Changes for drush_hosting_hosting_task module have been rolled back.
Command dispatch complete
Timer 'page' is 25.342 sec.

Have then been investigating with mig5 and jonhattan....

It seems that the introduction of drush_find_php() is causing the issue.

The function and the call to it were added here:
http://cvs.drupal.org/viewvc.py/drupal/contributions/modules/drush/inclu...
http://cvs.drupal.org/viewvc.py/drupal/contributions/modules/drush/inclu...

Rolling back to the version of drush before this was introduced resolves the problem and aegir tasks run okay again.

Jonhattan suggested that perhaps $_ENV is not being propagated between calls between backend tasks - and adding --php=$_ENV['_'] might solve the issue.

Comments

adrian’s picture

Priority: Normal » Critical

$_ENV['_'] would probably work fine if you only ever execute drush as 'php drush.php', but :

[_] => /Users/adrian/Projects/hosting/drush/drush.php

This is also just in the single command down.

this variable is completely unreliable.

anarcat’s picture

How about simply trying out 'php' instead of dying like this?

adrian’s picture

this goes away if you use the 'drush' shell script instead of drush.php

it also works if you run

'php /path/to/drush.php'

Perhaps what is needed is removing the +x from drush.php

adrian’s picture

Title: Introduction of drush_find_php() breaks Aegir tasks » Drush.php is no longer directly executable
Priority: Critical » Minor

Changing the status and title to match the actual issue.

'/path/to/drush.php' incorrectly populates the 'php' option

'php /path/to/drush.php' and '/path/to/drush' (ie: explicitly interpreted and the bash script) both work fine.

the php path is used to construct the command to do a drush_backend_invoke.

it should also be noted that just because php is correctly populated on this side, does not mean it will be correctly populated on a remote server.

moshe weitzman’s picture

Status: Active » Fixed

I removed the shebang from drush.php. The README looks OK to me. This is fixed, though I do think we have a lot of mistrained users out there who will be surprised when the next update.

anarcat’s picture

Status: Fixed » Needs review
StatusFileSize
new5.88 KB

So the actual issue here remains, that is: "Drush.php is no longer directly executable". In fact, now it's worse because the "shebang line" (the #! line) was removed from drush.php so now it's *really* not executable anymore.

Furthermore, it adds another layer of complexity: "php detection". That's something that shouldn't be necessary: drush is *already* started and therefore *knows* how to restart itself.

Allow me to demonstrate.

There are two possible ways to call drush: either directly (what's at stake here) and as an argument to the "php" commandline executable. [It's actually the same thing: calling drush directly (or any "shell script", which are really text files with a special header) just fires the first line with the drush script as an argument, on UNIX. But let's treat the two separate for the sake of the argument.]

Calling drush.php directly yields the following environment:

argv[0] => ./drush.php
_ENV["_"] => /home/anarcat/dist/drush/./drush.php

Calling php drush.php yeilds the following:

argv[0] => ./drush.php
_ENV["_"] => /usr/bin/php

In the first case, running argv[0] works all the time, because that's really how it was called. But that's not reliable enough because if we were called with php first, then it *may* not be executable directly (that would probably be an installation error, but that's another issue). So to call drush.php properly, we can't just call argv[0] directly, it's not reliable enough. (I guess that's why --php was introduced in the first place.) But it's still possible to reliably determine how to call drush again, it's just a matter of covering that other use case.

I am proposing to compare $argv0 and $_ so that we just detect that situation. If $_ doesn't end with $argv0, it means we must call drush using $_ $argv0. The attached patch does that. It also sends the find_php() script back to the simpletest file and removes the --php option, reverting that commit, in effect.

Also note that the way the code is right now (before or after my patch), it still doesn't take into account that remote servers may have different locations for the drush.php or php. That's something that can't be fixed simply by changing the php path (using --php) because then local invocations will fail (and it's quite possible to have local and remote call during a single run). That's something that needs to be fixed in another way. Besides, it's not really the remote *php* path, but rather the *drush.php* (with or without the php prefix) path that needs to be specified.

moshe weitzman’s picture

Seems to work for me. Needs testing by folks who were having troubles before. Next time you reroll

- put all this new nasty code into a function so we don't clutter top of drush.php
- use --no-prefix in git
- i removed the --php from the main help so that line of this patch is not applying cleanly.

owen barton’s picture

The patch in #6 does not work correctly in some situations when used with the "drush" script (which is the recommended way of invoking drush). Here is an example:
- In some environments php-cli is the correct executable to use on the command line. In these situations "php" is configured for a more restricted cgi environment, for example - and will not work correctly with Drush.
- The drush script uses /usr/bin/env to locate executables, as is the best practice for cross-platform scripts.
- The drush script will prefer php-cli, if it is found and will use it to run drush, with a command like "/usr/bin/env php-cli /full/path/to/drush.php mycommand myargs"
- In the attached patch $_SERVER['_'] only returns the name of the original executable - i.e. "/usr/bin/env".
- $_SERVER['argv'][0] only returns the php script - i.e. /full/path/to/drush.php
- Hence - DRUSH_COMMAND gets set to "/usr/bin/env /full/path/to/drush.php".
- When drush_invoke calls drush from within drush, it then calls a command like "/usr/bin/env /full/path/to/drush.php mycommand myargs"
- /usr/bin/env will happily invoke /full/path/to/drush.php directly, however the hashbang at the top of drush.php lacks the logic of the drush script, and hence will call "/usr/bin/env php", which of course finds the cgi build of php, and it all falls to bits.

To test (assuming you don't have php-cli in your environment) create one on your path that looks something like:

#!/bin/sh
echo php-cli WAS INVOKED!
/usr/bin/env php "$@"

Then create a command A that does a drush_backend_invoke to command B, where both commands print DRUSH_COMMAND and you should see (via the "php-cli WAS INVOKED") that "php-cli" was only invoked on the first call - on the second call only "php" was used.

There are other potential issues - for example if you run php with "php -c /home/fred/custom-php.ini" the -c parameter is dropped the second time around. Admittedly this is an edge case (and if you use the drush script you can't do this anyway), but is a similar symptom.

I am not sure what the solution is here. I am fairly sure that we won't be able to reliably figure out how to reexecute drush in all the various ways it can be executed from the php environment itself (a big fail is that php doesn't even provide a reliable way to extract the php executable path!).

Unless we can do this, we may need to revisit some of the other options mentioned above, such as a "--php" parameter.

An alternate option, which I would be interested in feedback on, would be to ensure (e.g. docs, by removing the hashbang, or using "#!drush" which seems to work) that drush is always run via the drush script. This way, we could always rerun it and ensure we end up with the same php executable and drush.php we started with. It seems like this would mean backend commands work correctly on most normal systems. We could find this simply by doing define('DRUSH_COMMAND', dirname(__FILE__) . '/drush'); or we could simply put ourselves in the directory we were called from, call "drush" and let the PATHs figure it out. The advantage of the second approach is that if you wanted you could provide a custom drush script in a "higher" PATH location to point a specific php and drush.php if for some reason the drush script isn't producing the right results. This approach could potentially be used in addition to the --php parameter, which would allow you to override the php.

moshe weitzman’s picture

Status: Needs review » Needs work
greg.1.anderson’s picture

StatusFileSize
new1.47 KB

This bug bit me when called via backend invoke with $hostname = null. In my case, drush was invoked with
/usr/bin/env php', and $_ENV['_'] was returning '/usr/bin/env'. The enclosed workaround adds the 'php' back on when it is detected to be missing, using /usr/bin/env to determine if php-cli or php should be used.

I agree with the above comments that $_ENV['_'] is not fully reliable, but at the moment, I have not come up with a better idea on how to find the php executable. The enclosed patch improves the current situation considerably, though.

greg.1.anderson’s picture

Title: Drush.php is no longer directly executable » Drush.php is no longer directly executable (can interfere with backend invoke)
Priority: Minor » Normal
Status: Needs work » Needs review
StatusFileSize
new738 bytes

It occurs to me that this situation is much improved if we contrive to make the common case (which is to say, invoking drush.php via the drush script) call drush in such a way that $_ENV['_'] is usable. This patch does exactly that. This patch should fix everyone who uses 'drush', and #10 will fix people who decide to call /usr/bin/env drush.php without using 'drush'. I think that covers just about everyone, but of course it's hard to tell without testing in all environments. (n.b. drush.php is still no longer directly executable, but I don't think that's a problem with these patches applied.)

I recommend committing both this patch and #10. Since this bug breaks backend invoke in some environments, I increased the priority from 'minor' to 'normal'.

greg.1.anderson’s picture

StatusFileSize
new725 bytes

TYPO. Do not use #11, use this version. Sorry.

anarcat’s picture

Assigned: Unassigned » anarcat
Status: Needs review » Needs work

For me, all of this doesn't address the core issue raised in the original post: drush.php should be directly executable. It's an optimisation that is perfectly worth it and should be allowed for platforms that have php in a well defined location. ubuntu and debian come to mind, other platforms can eitehr patch the drush.php in their packages or use the shell wrapper (which I do not object to).

I have, however, to explicitely request the drush.php to stay executable, in other words to keep the following shebang line on the top of the file:

#!/usr/bin/env php

In fact, I would rather have this be /usr/bin/php (as it would avoid yet another fork), but it's a compromise I'm ready to live with.

I'm working on a patch that will address all the comments here.

greg.1.anderson’s picture

@anarcat: Related to your comment in #6, how are you identifying the remote machine? If you are using a site alias (see #460924: Remote site aliases for Drush (Proposal and implementation)), you can specify the path to drush inside your path aliases; you might find this useful if you are interested in the optimization of directly executing drush.php.

Regarding #!/usr/bin/env php vs #!/usr/bin/php, I would tend to think that the default should be the variant that is most likely to work (the former), and platforms that want to optimize to something that might not work universally (the later) should be the one that patches. Just my opinion; since I use the shell wrapper, I am not strongly invested in this particular issue of drush.php executability, provided that backend invoke works.

anarcat’s picture

Priority: Normal » Critical
Status: Needs work » Needs review
StatusFileSize
new7.21 KB

So here's the long awaited patch. I'm really sorry I didn't have time to push this into 2.1... This long post tries to address all the concerns that were raised in this issue. Since I consider this issue quite critical (it breaks ubuntu and debian), I am marking this critical.

That env thing

From Owen's comments, I can see that there are problems with my patch when calling drush with "env". In my opinion, this should just be avoided altogether. Drush.php should be called in one of three ways:

1. through the drush shell script (apparently the recommended way)
2. through the php executable (e.g. php drush.php)
3. directly (e.g. ./drush.php or /usr/bin/drush.php)

Method (1) is most likely to be used by new drush users and should try everything it can to try to make drush run properly.

Method (2) will be used when the shell script will call drush or when people will call the script manually.

Method (3) will be used when drush is packaged and distributed properly. It's the optimal way to call drush in a well defined and controlled environment. I'm trying to make sure that option is still available while staying compatible with the other options.

There's another meta-method that applies to all of those that we should also support, and that is calling drush through sudo:

4. through sudo (e.g. sudo drush, sudo php drush.php or sudo drush.php)

Finally there is a myriad of other processes can call drush by exec()ing into it and therefore break it. /bin/env was stated as an example above. Basically, my stance on that is that if you're going to do crazy things like that, setup your environment properly (so that "php" just works) or use the bash wrapper. I suggest we focus on making only the above 4 methods work in every possible case.

I have tested the patch in the context of the debian package, and it works. My upload of the 2.1 version will require that I include this patch patch since squeeze uses dash.

Other concerns

So here are the other concerns that were explicitly raised with my patch:

- put all this new nasty code into a function so we don't clutter top of drush.php

I have created a new drush_find_drush() function in includes/environment.inc that's used to initialise the DRUSH_COMMAND constant. The reason why I was putting the code there and not using drush_find_php() (which is removed in my patch) is to have multiple places where that logic is defined. I assume that we do not need to know the path to PHP itself at this point.

- use --no-prefix in git

Of course, sorry about this.

- i removed the --php from the main help so that line of this patch is not applying cleanly.

Thank you very much for removing this non-sense. However, from what I can tell, there was a mistake in the code around that change:

$options['-h, --help'] = dt("The absolute path to your PHP intepreter.");

What does this do anyways?

Okay, so back from the top, my patch does the following. It builds upon the excellent reviews of Owen and Greg and refactors code here and there.

The patch removes the drush_find_php() command and duplicate code on top of drush.php in favor of a clearer and more complete drush_find_drush() that does minimal processing to determine the proper drush path solely based on the environment provided.

The drush shell script wrapper is also modified to avoid calling drush.php with env, as this is not required: the shell will do the proper path searching. I also use "which" instead of "php -v" to find if we have a php-cli binary, as I think this will be more efficient (I haven't tested this, unfortunatly).

The patch adds back the following shebang on top of drush.php:

#!/usr/bin/env php

I would really have this be #!/usr/bin/php instead, since we may as well encode a proper path that will work in most places if we're going to hardcode a path. But it was that way before and I'm going to respect that. Just keep in mind that we *are* assuming that env will be in /usr/bin/env and that will be yet another fork(), a small performance hit.

The patch also changes the SUDO_COMMAND heuristics. Now, we guess based on that variable *only* if $_SERVER["_"] is not set. That is because it's perfectly possible for someone to do this:

sudo sh
echo $SUDO_COMMAND
php drush.php help

Under the current conditions, that would fail: the $SUDO_COMMAND variable would be "/bin/sh" (or similar) and drush would guess that its php executable is not "php" but $SUDO_COMMAND (since for some reason $_SERVER["_"] is not set in PHP in those conditions). I think I fixed that.

To make sure all the methods described above work properly, the patch features a test command, drush test drush. This function should obviously be expanded once we have unit testing in place, but that's part of #483940: Unit testing library and I wanted to just get a quick test mechanism in place for now.

I believe the patch in its current shape cleans up a lot of cruft, clarifies the process of determining the drush binary and will support all configurations, provided people use the vendor-packaged drush binary, or the shell script. But please let us ship a proper binary with minimum effort! :)

Testing and constructive criticism really appreciated. The patch is developed on my 586466_commandline branch on git.koumbit.net.

anarcat’s picture

I missed #14 while writing #15, so I will answer here.

I am not familiar with site aliases. I consider those should not be required to execute drush directly. My basic point of view is the one of POLA (Principle Of Least Astonishment): php drush.php or ./drush.php can just work and it should. We shouldn't need to fiddle around with another shell to execute our drush shell, otherwise it's not really a shell. PHP is a (mostly) complete programming language (well, not quite, but you get my point) that doesn't need shell garbage around it to be functional.

I am not strongly attached to #!/usr/bin/php. I have not patched it in the debian package (since I wish to keep variance low), but I basically think it should be the shebang line: it's the most probably location of the php executable, and if we're going to hardcode a path, might as well guess the PHP path than the env path.. And anyways, others can use the shell wrapper.

However, I do not want that debate to block the "restore proper behavior" patch. :) I can improve upon it later.

anarcat’s picture

A final note on this: once there's a consensus on the patch, I will publish the 2.1 debian package.

zroger’s picture

I am having a different problem that seems to stem from the same issue.

I have a drush callback which uses drush_backend_invoke() to run a command against all sites in a multisite installation. Running this command directly against a single site works fine, but as soon as I use drush_backend_invoke to run this same command, I get errors. Using --debug, I can see that the command being run is:

Running: /usr/bin/env /home/d6-dev/drush/drush.php  --uri='http://example' --root='/home/d6-dev/public_html'  'status' --backend

Since the drush shell script is running drush.php with /usr/bin/env php, the $_ENV['_'] variable contains /usr/bin/env which is obviously not the right executable.

The logic in drush_find_php() needs to match the logic in the drush shell script to ensure that these inconsistencies don't creep up.

I haven't yet tested the above patch, hopefully I can get to that later tonight.

greg.1.anderson’s picture

Status: Needs review » Reviewed & tested by the community

I don't know if I qualify as "the community", but I did all the same set the status to "reviewed & tested by the community". This works very well in my environment.

Regarding this portion of the patch:

# We check for a command line (cli) version of php, and if found use that.
-  /usr/bin/env php-cli -v &> /dev/null
+  which php-cli >/dev/null 2>&1
   if [ "$?" = 0 ] ; then
-    /usr/bin/env php-cli $SCRIPT_PATH "$@"
+    php-cli $SCRIPT_PATH "$@"
   else
     # Alternatively we run with straight php, which works on most other systems.
-    /usr/bin/env php $SCRIPT_PATH "$@"
+    php $SCRIPT_PATH "$@"
   fi

In general, we use #!/usr/bin/env foo" instead of "#!foo" because the shebang requires a full path, and /usr/bin/env provides the function of searching $PATH for the executable. Using "/usr/bin/env php" instead of "php" in a script is just insanity; there is no additional functionality, as env will not change the environment unless you give it additional parameters. This in fact is why $_ENV['_'] was messed up in my environment; it is unusual to use env in this way in a script. I have to admit I was confused on this point, but it is now very clear to me.

Getting back to #!/usr/bin/env php vs #!/usr/bin/php, http://en.wikipedia.org/wiki/Shebang_(Unix) points out that env is sometimes /bin/env. I have no measure of how often php will be at some location other than /usr/bin/php, but I do concede your point that it's either one assumption or another in this instance.

Good job on the patch; I like it.

Anonymous’s picture

This is working well as expected and fixes the problem, thanks anarcat! Definitely looking forward to seeing this in drush 2.1 deb package too.

greg.1.anderson’s picture

@Roger: This is the same thing that I was experiencing, and I addressed it as you suggested in #10, above; however, note that the patch in #15 is better, and should clear up your problem as well. Please ignore #10 - #12.

moshe weitzman’s picture

Patch works for me. I want to give adrian and owen a couple days to review this before commit.

After commit, we can talk about releasing a new version so that debian does not fork and also talk about whether we go for 3.0 since we have the new site alias feature. our updatedb command does not work on d7 but that's d7's fault, not ours. still would hate to release 3.0 without that working.

anarcat’s picture

Don't worry about debian "forking": it's very common for Debian packages to diverge slightly from upstream, we don't call it a fork, we call that "patches". :) In fact, the debian package infrastructure is conceived as a patch (it adds a debian/ directory with meta files to the source). So we don't need to make an extra release just for debian, I can ship 2.1 with just the patch, unless you say that 2.1 is too broken to be shipped.

From what I understand, an eventual 2.2 may not be much better in the current state of HEAD, but I haven't been following HEAD closely enough to tell.

Discussions on 3.0 should be taken to a separate issue, in my opinion. :)

adrian’s picture

I'd suggest we make a drush 2.2 release with this fix, without the new remote stuff, and keep the remote stuff for a 3.0 release. Might take some shifting around in cvs (ie: branch on the 2.1 tag to a new branch, apply just this patch and make a release off it, then apply the patch to HEAD)

we're running into this issue a LOT in our usage, and it's making our life quite difficult. we have multiple people coming in every day with these error messages, and it seems to be _especially_ prevalent when running drush from crontab, and even the wrapper script doesn't work.

I'll test this patch shortly.

moshe weitzman’s picture

I have little taste for CVS gymnastics on this project. We're already pushing its silly limits by using tags like 6--2-1 when we mean 'All versions of Drupal'. The sitealias stuff had a long hard road getting committed. Its not getting uncommitted in order to make room for this issue. We'll commit this one, and then release with sitealias. Lets do as much testing as needed to assure that sitealias stuff works well with aegir. It goes without saying that Aegir is drush's biggest source of users and developers. We're not going to release while incompatible with it.

Still awaiting feedback on the patch from owen and adrian in particular.

greg.1.anderson’s picture

Regardless of the timing of the commit of this patch, whatever is at HEAD right now should be called "drush 3", perhaps in part due to site aliases, but more because of the fact that "drush sql load" is now gone. If this is likely to break a lot of scripts among the debian or aegir users, then Adrian's idea has some merit.

I will admit that the cvs tricks would be annoying; it might be better to make a 2.2 branch rather than back stuff out, if you go that route. cvs branches are broken, but you'd never need to re-merge this one. In defence of simplicity, though, people broken by the removal of sql load should almost always be able to fix their script by just replacing "sql load" with "sql sync".

This is just information; I'm not really taking a position here.

Annakan’s picture

Hello All

I am on a FreeBSD server and I think I am bitten by this bug even after downloading the latest Drupal.org available version of Drush.

Drush is now broken for me as ANY command besides the internal one fails with

>> php drush/drush.php hostmaster make $HOSTMASTER_DIR

Unable to automatically determine the path to the PHP interpreter.   [error]
Please supply the --php argument.
The command could not be executed successfully (returned:            [error]
drush/drush.php: cannot open ?php: No such file or directory
, code: 2)
An error occurred at function : drush_provision_hostmaster_make      [error]

Unless I am NOT on the latest version, I think this bug is still present at least on some unix platforms.

Can I help move this further ?

Some Complementary informations

>> whereis php
/usr/local/bin/php

>> whereis env 
/usr/bin/env

And on top of druhs.php the comment line is : // $Id: drush.php,v 1.76 2009/11/04 22:29:52 weitzman Exp $ , I tell this because I am a bit lost between versions and repositories at the moment with the git transition and drupal 7 move :)

Thanks a lot for your time.

PS: the consequence for "me" is that Aegir is broken since 4 weeks when I last updated drush and it broke the queue

adrian’s picture

Annakan : No currently released version of Aegir works with drush 2.1, only 0.4 alpha 3 will support drush 2.1

anarcat’s picture

@Annakan: try the patch above. Also: use the drush shell script instead of directly executing the drush.php PHP script, which expects php to be in /usr/bin/php (interested in working on a freebsd port? I can help! :).

anarcat’s picture

StatusFileSize
new7.15 KB

Here's a patch that should apply cleanly on 2.1.

owen barton’s picture

I haven't tested the DRUSH_COMMAND detection, but the drush script changes look great.

greg.1.anderson’s picture

StatusFileSize
new8.15 KB

The above patch does not apply cleanly against HEAD; this was due to a conflict with a change I made to backend.inc that Moshe already committed. Except for backend.inc, the rest of the patch does apply cleanly to HEAD.

I have attached a new patch re-rolled against HEAD that works for me (tested against site aliases and my committed changes to the Drush bootstrap process). So, use mine against HEAD, or Anarcat's if you branch off of 2.1.

(Maybe this is the same as #15... I didn't check for differences in Anacat's latest patch, I just assumed there were some.)

moshe weitzman’s picture

Status: Reviewed & tested by the community » Fixed

Committed. Thanks everyone.

I'm not 100% pleased with it though. On my machine, the drush bash script no longer works. It is picking up my MAMP php and using that whereas it just used `php` before which was correct; I have a custom PHP comes earlier in $PATH, and should be used.

anarcat’s picture

On that platform, you should be able to use just "drush.php" instead of the drush wrapper, that's the whole idea.

Otherwise, that problem was probably there before the patch: I haven't changed much of the shell wrapper really...

Annakan’s picture

@anarcat

ok but that's why I gave the version on top of the file 1.76 2009/11/04 is 2.1 ? :)

And I tried to move to 0.4 alpha4 but the process of moving use drush (http://cvs.drupal.org/viewvc/drupal/contributions/profiles/hostmaster/IN...).

I tried to just untar provision, hosting and Eldir in the "right" places, to no avail of course, since I suppose the "Drush" path problem is unrelated to the Aegir/drush version compatibility.

the DB update gave me some error about duplicate keys but since drush does not seem to bootstrap commands I was not able to investigate further.

I'll do a fresh install of aegir if needed as soon as I can issue drush commands without the path error.

Second :
I'll gladly help with a freebsd port, I'am not sure I'am up to it yet, PHP / system coding wise, but I'll gladly investigate, test and try as needed on my freebsd systems, I tried to do that for the 0.3 versions and would gladly contribute.

Annakan’s picture

@moshe weitzman

I'll try your path against Drush HEAD (on the cvs ? ) as soon as possible and report the result here.

thanks a lot for your time.

EDIT : I just used the last version from 11-10 (commited means something right, silly me) and drush info command works in a site directory.
But when I tried to do (as per the AEgir install.txt file)

$ php drush/drush.php hostmaster make $HOSTMASTER_DIR

I got

Unable to automatically determine the path to the PHP interpreter.   [error]
Please supply the --php argument.
The command could not be executed successfully (returned:            [error]
drush/drush.php: cannot open ?php: No such file or directory
, code: 2)
An error occurred at function : drush_provision_hostmaster_make      [error]

I need to investigate further but can't do it right now, I will try to bring more light in a few hours...
I am open to idea about what to check if something obvious come to mind.

Thanks a lot for your great help.

PS:the wrapper $ drush/drush hostmaster make $HOSTMASTER_DIR gives the same result

EDIT :
struck by lightning I tried this

$  drush/drush hostmaster make $HOSTMASTER_DIR  --php /usr/local/bin/php
The command could not be executed successfully (returned: 1: not found                                                                     [error]
, code: 127)
An error occurred at function : drush_provision_hostmaster_make                                                                            [error]

I don't know if it helps or muddy the water with improperly installed AEgir issues.

If it helps I can set up a remote debugging session from my local eclipse , take some time but It did it once already ;) , just need to know where to look at :)

Annakan’s picture

Just to add some informations but probably for my own understanding more than yours guys :)

I used yesteday head drush to update one of my site.

the "module code" update when fine but when drush tried to do the "updatedb" part it failed this way

...
Cache cleared.
You have pending database updates. Please run `drush updatedb` or visit update.php in your browser.                                        [warning]
Unable to automatically determine the path to the PHP interpreter. Please supply the --php argument.                                       [error]
The command could not be executed successfully (returned: /var/aegir/drush/drush.php: cannot open ?php: No such file or directory          [error]
, code: <em>2</em>)
An error occurred at function : drush_pm_post_update                                                                                       [error]

But than I did a simple $ drush updatedb it went perfectly fine.

Is it because when doing multiple commands Drush try to boostrap itself for each command, and THEN need to find the PhP interpretrer and fails as of now ?
Or am I looking into the wrong direction ?

Annakan’s picture

I decided to take a completely different route to determine the path of the php executable in case none of the environnement variable works.
I simply used the 'whereis -p' command from shellexec (allowed since drush need to be able to execute shell commands right ?)

I wrote a simple function

function drush_find_php_from_whereis(){
  $command_output=shell_exec('whereis -b php');
  list(,$php) = explode(':', $command_output,2);
  $php=trim($php);
  if($php=='') {
    drush_log(dt('Unable to automatically determine the path to the PHP interpreter with whereis from shell'), 'warning');
  };
  return $php;
}

Is it a really bad way of doing it ?
If not, I would gladly learn how to format and prepare the code for a patch.

Thanks a lot for your time.
and changed the drush_find_php function as such

function drush_find_php() {
  // Determine location of php command automatically, unless a command line argument is supplied.
  if (!$php = drush_get_option('php')) {
    if (!empty($_ENV['_'])) {
      // '_' is an environment variable set by the shell. It contains the command that was executed.
      $php = $_ENV['_'];
    }
    elseif (!empty($_ENV['SUDO_COMMAND'])) {
      // 'SUDO_COMMAND' is an environment variable set by the sudo program.
      // Extract only the PHP interpreter, not the rest of the command.
      list($php, ) = explode(' ', $_ENV['SUDO_COMMAND'], 2);
    }
    elseif(!$php = drush_find_php_from_whereis()) {
        drush_set_error('DRUSH_PHP_PATH_NOT_FOUND', dt('Unable to automatically determine the path to the PHP interpreter. Please supply the --php argument.'));
    }
  }
  return $php;
}
<code>

only the 

<code>
    elseif(!$php = drush_find_php_from_whereis()) {
        drush_set_error('DRUSH_PHP_PATH_NOT_FOUND', dt('Unable to automatically determine the path to the PHP interpreter. Please supply the --php argument.'));
    }

line is new.

is it a bad solution ?
I know it does not cover all the cases (if some interpreter invocation environnement must use php-cli, right ?) but since it is a last resort fall-back.
And in more way that none 'whereis' is the function supposed to know where to look at in a system dependent manner for an executable properly installed on a system....

greg.1.anderson’s picture

I suspect that there are still two cases not covered in relaunching drush:

  1. Calling 'php drush.php' rather than calling 'drush.php' directly (deprecated)?
  2. Calling drush via a relative path such as 'drush/drush'

Drush changes the cwd when it bootstraps the Drupal root, so if 'drush' is not on your path and $_ENV['_'] is 'drush/drush', then Drush will not be able to re-launch itself after the cwd changes. To fix this problem, detect a relative path in $_ENV['_'] and prefix the saved working directory variable before re-launching Drush. Look in environment.inc for the cwd-saving code. On linux, absolute paths start with '/', but you need to also expect to see c:\ on Windows. I'm not sure if there are other patterns we'd have to watch for on other platforms.

I'm not sure about point #1 yet; I'd need to do some experiments first, when I have time. I suspect that 'whereis php' is slow.

anarcat’s picture

@Anakkan: you don't seem to be using the latest version (HEAD or 2.1 with a patch), so please try again with the CVS version and reopen an issue (or open a support request) if that's still a problem.

anarcat’s picture

@greg.1.anderson - 1) should be covered, it's one of the use case I detailed above and I tested it thoroughly. In fact, it's how the shell wrapper calls drush.php itself so it *has* to work.

2) relative paths should also work as I am using "realpath()" to dereference paths when finding drush. I haven't tested that thoroughly however, and it may not happen everywhere it should. In fact, the only case where this may fail is where *php* was called with a relative path:

    $drush = realpath($_SERVER['_']);
  } else {
    // not called directly, we were called as an argument to PHP, which
    // should be in $GLOBALS['_']
    $drush = $_SERVER['_'] . ' ' . realpath($_SERVER['argv'][0]);

... which is an edge case that could easily be fixed by adding realpath() above.

Finally, which is really faster than php here:

anarcat@ceres:~$ time which php > /dev/null

real    0m0.004s
user    0m0.000s
sys     0m0.000s
anarcat@ceres:~$ time php -v > /dev/null

real    0m0.095s
user    0m0.036s
sys     0m0.012s

That's about 20 times faster.

anarcat’s picture

Status: Fixed » Needs work

Oh I'm so happy to announce this evil nightmare is not fixed yet.

The problem is we assumed PHP provided us with a nice $_ variable, whereas that variable is actually an undocumented (from the manpage, at least) environment variable from bash that has been vaguely defined as "the last command ran" by someone else. That variable is not present in dash, or if it is, it's because it is inherited by a parent bash process, which will wreak even more havoc.

So we can't rely on $_ at all, at this point.

What I would suggest at this point would be to define a constant on the PHP commandline that would point to the php binary if it's not "php" and in the path. That would be the job of the shell wrapper to guess all this stuff. Otherwise, the .php script would just execute itself and ignore $_ (which is not reliable) and assume php is in the path unless said otherwise.

anarcat’s picture

So yes, basically, I'm proposing to bring back the dreaded --php option. :(

adrian’s picture

We should _always_ assume 'php' unless otherwise specified.

i think the main issue with this is we weren't using the obvious default that would work for 99% of cases.

anarcat’s picture

Status: Needs work » Fixed

The issue here was fixed: drush.php is executable. We now have a very specific interoperability issue with drush, for which I have opened a specific issue in #637574: drush finds the wrong php executable when executing under dash.

Annakan’s picture

@anarcat
Much apologies you were right :)
I got mixed up in the git/CVS/head maze ;)

Works fine now (on freeBSD at least).

thanks a lot.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.