symfony / panther

A browser testing and web crawling library for PHP and Symfony
MIT License
2.93k stars 220 forks source link

geckodriver binary not found #433

Open javlae2 opened 3 years ago

javlae2 commented 3 years ago

Hello everyone. I am using version 1.0.1 with Symfony 5.2 on an Ubuntu 20.04. I was using 0.9 in another project with no problems, but this one starting acting up strangely.

I have already installed the gecko and chromium drivers following the readme.

When trying to create a new Firefox client, I get this error:

RuntimeException:

message: ""geckodriver" binary not found. Install it using the package manager of your operating system or by running "composer require --dev dbrekelmans/bdi && vendor/bin/bdi detect drivers". "

code: 0

file: "/var/www/scraper/vendor/symfony/panther/src/ProcessManager/FirefoxManager.php"

line: 87

I have checked in the project's drivers/ folder and both of them are in fact there, with execution permissions and the right owner. Both drivers are also found under /usr/bin/ folder.

When detecting the drivers I correctly get this:

$ vendor/bin/bdi detect drivers

 [OK] chromedriver 88.0.4324.96 installed to drivers/chromedriver

 [OK] geckodriver 0.29.0 installed to drivers/geckodriver

Here's the portion of my code:

        $client = Client::createFirefoxClient();
        $crawler = $client->request('GET', $url);
        $crawler
            ->filter($find)->each(function ($node) use ($webSiteDepartment) {
                $element = new Document();
                $element->setTitle($node->text());
                //A lot of code here, non relevant to this issue
                $this->foundElements[] = $element;
            });

        return $this->foundElements;

I have already:

What could be the possible cause of this problem? Is there any additional optional configuration that I might be missing?

Thanks a lot in advance!

EDIT: This happens in an AWS EC2 Instance. I replicated the same project and exact same config to another server and it worked fine! Still, not able to get it to work in an AWS though.

halfer commented 3 years ago

I do this in my Dockerfile:

composer install \
    && vendor/bin/bdi detect drivers -vv \
    && mv drivers/* /usr/local/bin/

This just puts my driver (chromedriver) in my system path. Make sure you try which geckodriver to ensure it is visible to your PHP code. Maybe even try putting that in your PHPUnit bootstrap, in case there is something weird going on with your path in PHP.

javlae2 commented 3 years ago

Thanks for the response @halfer I have tried it with no luck. Still get this error: "geckodriver" binary not found. Install it using the package manager of your operating system or by running "composer require --dev dbrekelmans/bdi && vendor/bin/bdi detect drivers".

And I do have the drivers there:

$ which geckodriver
/usr/local/bin/geckodriver
dunglas commented 3 years ago

Is this directory in your PATH?

javlae2 commented 3 years ago

@dunglas yes it is.

$ echo "$PATH"
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
halfer commented 3 years ago

@javlae2 you could try hardwiring the path to your driver and supplying it in your client creation call. I do this for Chrome:

        $client = Client::createChromeClient(
            $this->getTestDir() . '/scripts/chromedriver',
            $this->getChromeArguments(),
            $this->getDriverOptions()
        );

In my case .../scripts/chromedriver is a shell script that calls the real chromedriver, which is in my path. In your case you could just point to your real geckodriver (the format of the command is the same - the first param is the path to the driver binary or something that will invoke it).

javlae2 commented 3 years ago

Thank you @halfer

I am providing it the exact binary location like this: $client = Client::createFirefoxClient( '/usr/local/bin/geckodriver' );

The binary is there: ~$ which geckodriver /usr/local/bin/geckodriver

I even re-downloaded it from source and manually gave it all permissions. but even if the binary is there in the specified location, I get a similar error (not exactly the same as before though): Expected browser binary location, but unable to find binary in default location, no 'moz:firefoxOptions.binary' capability provided, and no binary flag set on the command line

Would you mind sharing your $this->getChromeArguments(), $this->getDriverOptions() functions?

ThomasLandauer commented 3 years ago

@javlae2 I hunted this down to ExecutableFinder::find() What does getenv('PATH') give you? If false, then see https://stackoverflow.com/q/19659675/1668200

@dunglas This is a serious problem and it should be explained somewhere! PHP-FPM is not exposing any environment variables (at least this is the default setting for PHP 8.0). So when the driver is somewhere in /usr/..., Panther can't find it. And it gets worse: Cause when copying the driver to /drivers, that doesn't help either: Panther does now find it, but geckodriver can't find Firefox ;-) (I'm inferring this from the "Expected browser binary location..." message) Idea: Is there a way to pass command line arguments when starting geckodriver? Cause solving it this way might be easier than telling people to edit their www.conf ;-)

javlae2 commented 3 years ago

Thank you @ThomasLandauer yes! getenv('PATH') was returning false

I uncommented the line that defines the path env[PATH] in /etc/php/7.4/fpm/pool.d/www.conf and now geckodriver is able to find firefox.

Thanks again for finding the issue!