OSError (Errno 8] when running chromedriver (Webdriver / Selenium / Python / AppDaemon)

I would like to employ this python script which runs nicely on my Windows PC also in HA (2022.7.3):

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()), options=chrome_options)
driver.get('http://192.168.2.1/html/login/status.html')
try:
    element = WebDriverWait(driver, 20).until(
        EC.visibility_of_element_located((By.ID, 'var_dsl_downstream'))
    )
finally:
    print(element.text)
    driver.quit()

I tried doing this will AppDaemon (0.9.0) but even this short script::

import hassapi as hass
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
class SpeedRead(hass.Hass):
  def initialize(self):
    driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()))

fails with these errors:

2022-07-12 23:54:09.944709 WARNING Speed_Read: ------------------------------------------------------------
2022-07-12 23:54:09.945267 WARNING Speed_Read: Unexpected error running initialize() for Speed_Read
2022-07-12 23:54:09.945575 WARNING Speed_Read: ------------------------------------------------------------
2022-07-12 23:54:09.954721 WARNING Speed_Read: Traceback (most recent call last):
File “/usr/lib/python3.10/site-packages/appdaemon/app_management.py”, line 165, in initialize_app
await utils.run_in_executor(self, init)
File “/usr/lib/python3.10/site-packages/appdaemon/utils.py”, line 337, in run_in_executor
response = future.result()
File “/usr/lib/python3.10/concurrent/futures/thread.py”, line 58, in run
result = self.fn(*self.args, **self.kwargs)
File “/config/appdaemon/apps/speedread.py”, line 23, in initialize
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()))
File “/usr/lib/python3.10/site-packages/selenium/webdriver/chrome/webdriver.py”, line 69, in init
super().init(DesiredCapabilities.CHROME[‘browserName’], “goog”,
File “/usr/lib/python3.10/site-packages/selenium/webdriver/chromium/webdriver.py”, line 89, in init
self.service.start()
File “/usr/lib/python3.10/site-packages/selenium/webdriver/common/service.py”, line 71, in start
self.process = subprocess.Popen(cmd, env=self.env,
File “/usr/lib/python3.10/subprocess.py”, line 966, in init
self._execute_child(args, executable, preexec_fn, close_fds,
File “/usr/lib/python3.10/subprocess.py”, line 1842, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
OSError: [Errno 8] Exec format error: ‘/root/.wdm/drivers/chromedriver/linux64/103.0.5060/chromedriver’
2022-07-12 23:54:09.955187 WARNING Speed_Read: ------------------------------------------------------------

I also tried with ChromiumService plus the chrome type information (which also works on my PC) but same problem. What am I doing wrong? Any help would be highly appreciated!

Added later:
Add-on: AppDaemon
Python Apps and Dashboard using AppDaemon 4.x for Home Assistant
Add-on version: 0.9.0
You are running the latest version of this add-on.
System: Home Assistant OS 8.2 (aarch64 / odroid-n2)
Home Assistant Core: 2022.7.3
Home Assistant Supervisor: 2022.07.0

Never used selenium but seems like it’s unable to find the chromedriver. You sure it’s loaded into the docker environment that AD is running in?

When starting appdaemon I get:

…
(1/1) Installing chromium-chromedriver (102.0.5005.158-r0)
…

Is this what you were asking for?

Can’t really say because I’ve never ran selenium but it’s entirely possible the version of selenium you’re using might be the issue with 3.10 and not so much AD.

Having the same problem.

Tried several ways of using chromedriver (problems with PATH, packages, etc) and now that I finally have the webdriver manager working with ChromeDriverManager().install() I got this error of Exec format error…

I had tried another code (from here: veolia-idf/veolia-idf-domoticz.py at e2a6b760983c2620fb1f3721e452d937d6173ec8 · mdeweerd/veolia-idf · GitHub) and run in the same error (or something similar, like can’t find or execute the chromedriver)…

Anyone has some simple code to test chromedriver in HA? I tried to run the script in a VM and send the result over MQTT, but my ISP use a CGNAT (I’m trying to get a public IP, but with no much hope)… anyway… I’m just playing with some codes and testing my poor skills, so nothing important… but would appreciate any help… thanks in advance! =]

I just stumbled on this thread, I adapted veolia-idf to AppDaemon.

A similar error is not the same error and at this level details matter.

In the initial message, there is an OSError indicating that the executable type is not compatible with the architecure. For instance: calling an arm executable on an x86 machine, or the other way around.

When veolia_idf is launched correctly, it will show the path it finds for the chromedriver and chromiumbrowser - in my generic-x86 setup this works:

2023-02-02 01:14:22,868 : OK : "chromium" = "/usr/bin/chromium-browser"
2023-02-02 01:14:22,870 : OK : "chromedriver" = "/usr/bin/chromedriver"

As indicated the OSError is about an Exec format error. It looks like the OS under which the script is executed is not compatible with the binaries of the driver.

You can check the types by running “file” on them in the AppDaemon container.

Here is an AppDaemon script and setup that will run ‘/usr/bin/file’ on some files. There are some configurations to get the directory contents of the system (which helped finding where file was).

This script will launch the system command you specify and send the output to log files (if specified).

Script “call_script.py”:

import os
import sys
import subprocess as s

import adbase as ad
import hassapi as hass


class CallScript(hass.Hass):
    def initialize(self):
        event_name = "call_script"
        if "event" in self.args:
            event_name = self.args["event"]
        self.listen_event(self.call_script, event_name)
        self.call_script()

    @ad.app_lock
    def call_script(self, *args, **kwargs):  # pylint: disable=unused-argument
        if "script" not in self.args:
            raise("Missing script parameter for CallScript")

        script_args = [self.args["script"]]
        if "args" in self.args:
             s_args = self.args["args"]
             script_args.extend(s_args)

        out = sys.stdout
        err = sys.stderr
        closeout = False
        closeerr = False

        if "outfile" in self.args:
            out =  open(self.args["outfile"], "w")
            closeout = True
        if "errfile" in self.args:
            err =  open(self.args["errfile"], "w")
            closeerr = True

        s.call(script_args, stdout=out, stderr=err)

        # Close files as needed
        if closeout:
             out.close()
        if closeerr:
             err.close()

AppDaemon configuration `script.yaml’:

script1:
  module: call_script
  class: CallScript
  event: call_lsAll
  script: /bin/ls
  outfile: /config/appdaemon/apps/test.log
  errfile: /config/appdaemon/apps/testerr.log
  args:
    - "-lRt"
    - /config
script2:
  module: call_script
  class: CallScript
  event: call_showusrbin
  script: /bin/ls
  outfile: /config/appdaemon/apps/test.log
  errfile: /config/appdaemon/apps/testerr.log
  args:
    - "-lRt"
    - /usr/bin
chrome_filetype:
   module: call_script
   class: CallScript
   event: call_file
   script: /usr/bin/file
   args:
     - /usr/bin/chromedriver
     - /usr/bin/chromium-browser
     - /usr/bin/python3
     - /usr/bin/python3.10
     - /usr/lib/chromium/chromedriver
   outfile: /config/appdaemon/apps/script.log
   errfile: /config/appdaemon/apps/scripterr.log
ls_data:
  module: call_script
  class: CallScript
  event: call_data
  script: /bin/ls
  outfile: /config/appdaemon/apps/test2.log
  errfile: /config/appdaemon/apps/test2err.log
  args:
    - "-lRt"
    - /data

When I trigger the event ‘call_file’, I get the following in /config/appdaemon/apps/script.log:

/usr/bin/chromedriver:          symbolic link to /usr/lib/chromium/chromedriver
/usr/bin/chromium-browser:      symbolic link to /usr/lib/chromium/chromium-launcher.sh
/usr/bin/python3:               symbolic link to python3.10
/usr/bin/python3.10:            ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, stripped
/usr/lib/chromium/chromedriver: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, BuildID[sha1]=e28004cc68378030824ae98424434832fbb56162, stripped

The type of the python3 executable is the same as the one for chromedriver, so that is good. And I am on a generic-x86 installation - the architecture is ok for me.

So you’ld have to check that. With the event ‘call_showusrbin’ you can list the contents of /usr/bin

EDIT: OSErr 8 can also occur when a shebang is missing at the head of a file.
That is, at the start of a shell script we should have something like:

#!/bin/sh

and /bin/sh should exist.

We can see above that the browser itself is launched by a script. You could check that it has a working shebang by performing ‘/bin/cat’ on the file. If it says “#!/bin/bash” you could consider installing bash for instance. If the shebang is missing, the default should be #!/bin/sh which is part of busybox - however you could add the missing line at the top of the shell script (by using other scripts?).

1 Like

Thank you for your reply. I’m really far from undertand all the complexity in HA environment (tried this year to use Dockers and oh my, soo much to learn) so I just give up from running custom scripts, even to build I custom integration I was lost so I get a server with debian running scripts and sending results to a SQL database, and them a sensor in HA getting this value. I tried MQTT too and works but I was more familiarized with SQL, so…

But I really apreciate this reply with this information, propably useful in the future or for others users. Someday I will try to undertand de minimum to build a custom integration, just for the hobby, because HA is amazing and I’m kind of addicted to that…

Sorry for my english or anything and thanks again. =]