Reputation: 3821
I'm a noob as it comes to linux setup (and heroku), so apologies if this question is basic.
I want to run selenium webkit (in ruby) on Heroku. I face a difficulty that my script cannot find Chrome binary file.
I actually got chrome to work by itself:
~ $ chromedriver
Starting ChromeDriver 2.22.397932 (282ed7cf89cf0053b6542e0d0f039d4123bbb6ad) on port 9515
Only local connections are allowed.
chromedriver
being a file that I copied from /app/vendor/bundle/bin/chromedriver
, just to make it easier for now. chromedriver
file there exists because I installed chromedriver-helper gem. The gem was supposed to make the binary file available for ruby processes but didn't.
I've also tried setting path explicitly, e.g. Selenium::WebDriver::Chrome.driver_path = 'chromedriver'
in my ruby code, with the aforementioned file located in the root category.
It all works perfectly locally (with or without the driver_path
)
What can be the cause? I've read this SO thread from years ago, but it seems outdated to me. Any ideas would be greatly appreciated!
error trace:
~ $ ruby bin/run.rb
/app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/response.rb:70:in `assert_ok': unknown error: cannot find Chrome binary (Selenium::WebDriver::Error::UnknownError)
(Driver info: chromedriver=2.22.397932 (282ed7cf89cf0053b6542e0d0f039d4123bbb6ad),platform=Linux 3.13.0-91-generic x86_64)
from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/response.rb:34:in `initialize'
from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/http/common.rb:78:in `new'
from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/http/common.rb:78:in `create_response'
from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/http/default.rb:90:in `request'
from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/http/common.rb:59:in `call'
from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/bridge.rb:649:in `raw_execute'
from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/bridge.rb:123:in `create_session'
from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/remote/bridge.rb:87:in `initialize'
from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/chrome/bridge.rb:48:in `initialize'
from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/common/driver.rb:64:in `new'
from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/common/driver.rb:64:in `for'
from /app/vendor/bundle/ruby/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver.rb:84:in `for'
from /app/lib/mealpass_orderer.rb:12:in `initialize'
from /app/lib/mealpass_orderer.rb:8:in `new'
from /app/lib/mealpass_orderer.rb:8:in `run'
from bin/run.rb:3:in `<main>'
UPDATE:
I tried the same with AWS EC2 server (launched instance, cloned git repo, installed all dependencies). The same happens there as well. That is, able to execute chromedriver from terminal, but seeing same error when run the script.
Upvotes: 6
Views: 5212
Reputation: 1
I know this comes in a bit late. But I had the same issue, and just figured it out. I was going NUTS. Turns out Heroku doesn't really maintain their buildpacks. Therefore, install these buildpacks:
https://github.com/awl19/heroku-buildpack-google-chrome https://github.com/awl19/heroku-buildpack-chromedriver
and of course your heroku/ruby buildpack after those two.
Boom. It'll work like clockwork. Additionally super important, don't forget to explicitly quit the browser after each request, or after a certain amount of time, otherwise it'll be spawned indefinitely, will use up all of your memory, and eventually kill the server. You can do that with
session.quit
I guess for you (wherever you're calling a new capybara session.. maybe inyour controller?) it should look something like this:
session = Capybara::Session.new(:selenium)
// your browser actions or logic here
session.quit
Upvotes: 0
Reputation: 169
Here's a minimal configuration that's worked for me. You'll need to have the right buildpacks to install chrome too, it looks like you're only installing chromedriver which is a separate binary.
https://github.com/jormon/minimal-chrome-on-heroku-xvfb
You can test one-button deploy it to Heroku using the button on the README.md.
Let me know how it goes!
Upvotes: 1
Reputation: 1001
ChromeDriver is just a driver for Chrome. It needs the actual Chrome browser installed on the same machine to actually work.
Heroku doesn't have Chrome installed on its dynos by default. You need to use a buildpack that installs Chrome. For example:
https://github.com/dwayhs/heroku-buildpack-chrome
You can see how it fetches Chrome:
https://github.com/dwayhs/heroku-buildpack-chrome/blob/master/bin/compile#L36-38
Upvotes: 5
Reputation: 3406
ANSWER
YOUR_PATH = 'whatever/your/path/is' # to your bin dir
CURRENT_DIR = File.expand_path(File.dirname(__FILE__))
CHROMEDRIVER_FN = File.join(CURRENT_DIR, YOUR_PATH, "bin/chromedriver")
# —OR—
#CHROMEDRIVER_FN = File.join(File.absolute_path('..', CURRENT_DIR), YOUR_PATH, "bin/chromedriver")
Selenium::WebDriver::Chrome.driver_path = CHROMEDRIVER_FN
CONTEXT
The example below shows my setup for Selenium Chromedriver in a recent Ruby project.
1) The file structure:
ruby_app/
├── Gemfile
├── Gemfile.lock
├── History.txt
├── Manifest.txt
├── README.md
├── Rakefile
├── bin
│ └── chromedriver
├── doc
├── lib
│ └── ruby_app.rb
└── test
├── test_files
│ ├── test_config.yml
│ └── uris_array_dump.yml
├── test_ruby_app.rb
├── test_google.rb
├── test_helper.rb
└── test_output
2) In test/test_helper.rb
:
TEST_DIR = File.expand_path(File.dirname(__FILE__))
TEST_FILES = File.join(TEST_DIR, "test_files")
TEST_OUTPUT = File.join(TEST_DIR, "test_output")
CHROMEDRIVER_FN = File.join(File.absolute_path('..', TEST_DIR), "bin", "chromedriver")
The above code uses File.absolute_path
, see: http://ruby-doc.org/core-2.3.1/File.html#method-c-absolute_path
Converts a pathname to an absolute pathname. Relative paths are referenced from the current working directory of the process unless
dir_string
is given, in which case it will be used as the starting point.
3) In test/test_google.rb
:
Selenium::WebDriver::Chrome.driver_path = CHROMEDRIVER_FN
Upvotes: 1