PiJuice Running As Root

Hey Guys,

I’m having issues running PiJuice_cli on the DietPi install I have. I can successfully launch the shell GUI with pijuice_cli, but it crashes when you pick any of options. The error varies depending on what CLI option you choose.

Now I’m not sure if this is correct, but from what I saw most people are running/logging in to DietPi as root?
As a test I’ve tried starting it with pijuice user via “sudo -u pijuice pijuice_cli” and it works perfectly. Obviously, this is some sort of permissions issue, right?

Thanks for any help in advance.

Required Information

  • DietPi version | cat /boot/dietpi/.version
G_DIETPI_VERSION_SUB=20
G_DIETPI_VERSION_RC=1
G_GITBRANCH='master'
G_GITOWNER='MichaIng'
G_LIVE_PATCH_STATUS[0]='applied'
  • Distro version | echo $G_DISTRO_NAME $G_RASPBIAN
    bookworm 1
  • Kernel version | uname -a
    Linux RaspberryPi6.1.21+ #1642 Mon Apr 3 17:19:14 BST 2023 armv6l GNU/Linux
  • Architecture | dpkg --print-architecture
    armhf
  • SBC model | echo $G_HW_MODEL_NAME or (EG: RPi3)
    RPi Zero W (armv6l)

Additional Information (if applicable)

  • Software title | (EG: Nextcloud)
    PiJuice
  • Was the software title installed freshly or updated/migrated?
    Fresh Install
  • Can this issue be replicated on a fresh installation of DietPi?
    Yes

Probably the software is not allowed to run as root user. Some app explicitly checks this to avoid too powerful access. Some kind of security.

Can you share some error messages you receive if you are running as user root?

Thanks @Joulinar,

What is the recommended setup when deploying DietPi in terms of user management?
Do most people run from root or dietpi user? or do the make a new one altogether and disable dietpi?
Should I not be using root?

Also please find:
image

  • When selecting Status
Traceback (most recent call last):
  File "/usr/bin/pijuice_cli.py", line 2087, in <module>
    loop.run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 287, in run
    self._run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 385, in _run
    self.event_loop.run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 790, in run
    self._loop()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 827, in _loop
    self._watch_files[fd]()
  File "/usr/lib/python3/dist-packages/urwid/raw_display.py", line 416, in <lambda>
    wrapper = lambda: self.parse_input(
                      ^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/raw_display.py", line 515, in parse_input
    callback(processed, processed_codes)
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 412, in _update
    self.process_input(keys)
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 513, in process_input
    k = self._topmost_widget.keypress(self.screen_size, k)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/container.py", line 598, in keypress
    return self.top_w.keypress(self.top_w_size(size,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/container.py", line 1626, in keypress
    key = self.focus.keypress(tsize, key)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/container.py", line 2316, in keypress
    key = w.keypress((mc,) + size[1:], key)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/decoration.py", line 622, in keypress
    return self._original_widget.keypress(maxvals, key)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/listbox.py", line 968, in keypress
    key = focus_widget.keypress((maxcol,),key)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/decoration.py", line 622, in keypress
    return self._original_widget.keypress(maxvals, key)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/wimp.py", line 543, in keypress
    self._emit('click')
  File "/usr/lib/python3/dist-packages/urwid/widget.py", line 461, in _emit
    signals.emit_signal(self, name, self, *args)
  File "/usr/lib/python3/dist-packages/urwid/signals.py", line 265, in emit
    result |= self._call_callback(callback, user_arg, user_args, args)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/signals.py", line 295, in _call_callback
    return bool(callback(*args_to_pass))
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/bin/pijuice_cli.py", line 1994, in item_chosen
    callback()
  File "/usr/bin/pijuice_cli.py", line 209, in __init__
    self.main()
  File "/usr/bin/pijuice_cli.py", line 269, in main
    status_args = self.get_status()
                  ^^^^^^^^^^^^^^^^^
  File "/usr/bin/pijuice_cli.py", line 215, in get_status
    status = pijuice.status.GetStatus().get('data', {})
             ^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'status'
  • When selecting General
    Unable to connect to device

  • When selecting Buttons

Traceback (most recent call last):
  File "/usr/bin/pijuice_cli.py", line 2087, in <module>
    loop.run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 287, in run
    self._run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 385, in _run
    self.event_loop.run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 790, in run
    self._loop()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 827, in _loop
    self._watch_files[fd]()
  File "/usr/lib/python3/dist-packages/urwid/raw_display.py", line 416, in <lambda>
    wrapper = lambda: self.parse_input(
                      ^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/raw_display.py", line 515, in parse_input
    callback(processed, processed_codes)
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 412, in _update
    self.process_input(keys)
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 513, in process_input
    k = self._topmost_widget.keypress(self.screen_size, k)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/container.py", line 598, in keypress
    return self.top_w.keypress(self.top_w_size(size,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/container.py", line 1626, in keypress
    key = self.focus.keypress(tsize, key)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/container.py", line 2316, in keypress
    key = w.keypress((mc,) + size[1:], key)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/decoration.py", line 622, in keypress
    return self._original_widget.keypress(maxvals, key)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/listbox.py", line 968, in keypress
    key = focus_widget.keypress((maxcol,),key)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/decoration.py", line 622, in keypress
    return self._original_widget.keypress(maxvals, key)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/wimp.py", line 543, in keypress
    self._emit('click')
  File "/usr/lib/python3/dist-packages/urwid/widget.py", line 461, in _emit
    signals.emit_signal(self, name, self, *args)
  File "/usr/lib/python3/dist-packages/urwid/signals.py", line 265, in emit
    result |= self._call_callback(callback, user_arg, user_args, args)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/signals.py", line 295, in _call_callback
    return bool(callback(*args_to_pass))
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/bin/pijuice_cli.py", line 1994, in item_chosen
    callback()
  File "/usr/bin/pijuice_cli.py", line 713, in __init__
    self.device_config = self._get_device_config()
                         ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/bin/pijuice_cli.py", line 797, in _get_device_config
    for button in self.BUTTONS:
                  ^^^^^^^^^^^^
AttributeError: 'ButtonsTab' object has no attribute 'BUTTONS'
  • When selecting LEDs
Traceback (most recent call last):
  File "/usr/bin/pijuice_cli.py", line 2087, in <module>
    loop.run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 287, in run
    self._run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 385, in _run
    self.event_loop.run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 790, in run
    self._loop()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 827, in _loop
    self._watch_files[fd]()
  File "/usr/lib/python3/dist-packages/urwid/raw_display.py", line 416, in <lambda>
    wrapper = lambda: self.parse_input(
                      ^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/raw_display.py", line 515, in parse_input
    callback(processed, processed_codes)
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 412, in _update
    self.process_input(keys)
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 513, in process_input
    k = self._topmost_widget.keypress(self.screen_size, k)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/container.py", line 598, in keypress
    return self.top_w.keypress(self.top_w_size(size,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/container.py", line 1626, in keypress
    key = self.focus.keypress(tsize, key)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/container.py", line 2316, in keypress
    key = w.keypress((mc,) + size[1:], key)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/decoration.py", line 622, in keypress
    return self._original_widget.keypress(maxvals, key)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/listbox.py", line 968, in keypress
    key = focus_widget.keypress((maxcol,),key)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/decoration.py", line 622, in keypress
    return self._original_widget.keypress(maxvals, key)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/wimp.py", line 543, in keypress
    self._emit('click')
  File "/usr/lib/python3/dist-packages/urwid/widget.py", line 461, in _emit
    signals.emit_signal(self, name, self, *args)
  File "/usr/lib/python3/dist-packages/urwid/signals.py", line 265, in emit
    result |= self._call_callback(callback, user_arg, user_args, args)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/signals.py", line 295, in _call_callback
    return bool(callback(*args_to_pass))
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/bin/pijuice_cli.py", line 1994, in item_chosen
    callback()
  File "/usr/bin/pijuice_cli.py", line 614, in __init__
    self._refresh_settings()
  File "/usr/bin/pijuice_cli.py", line 658, in _refresh_settings
    self.current_config = self._get_led_config()
                          ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/bin/pijuice_cli.py", line 646, in _get_led_config
    for i in range(len(self.LED_NAMES)):
                       ^^^^^^^^^^^^^^
AttributeError: 'LEDTab' object has no attribute 'LED_NAMES'
  • When selecting the Battery profile
Traceback (most recent call last):
  File "/usr/bin/pijuice_cli.py", line 2087, in <module>
    loop.run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 287, in run
    self._run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 385, in _run
    self.event_loop.run()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 790, in run
    self._loop()
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 827, in _loop
    self._watch_files[fd]()
  File "/usr/lib/python3/dist-packages/urwid/raw_display.py", line 416, in <lambda>
    wrapper = lambda: self.parse_input(
                      ^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/raw_display.py", line 515, in parse_input
    callback(processed, processed_codes)
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 412, in _update
    self.process_input(keys)
  File "/usr/lib/python3/dist-packages/urwid/main_loop.py", line 513, in process_input
    k = self._topmost_widget.keypress(self.screen_size, k)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/container.py", line 598, in keypress
    return self.top_w.keypress(self.top_w_size(size,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/container.py", line 1626, in keypress
    key = self.focus.keypress(tsize, key)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/container.py", line 2316, in keypress
    key = w.keypress((mc,) + size[1:], key)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/decoration.py", line 622, in keypress
    return self._original_widget.keypress(maxvals, key)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/listbox.py", line 968, in keypress
    key = focus_widget.keypress((maxcol,),key)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/decoration.py", line 622, in keypress
    return self._original_widget.keypress(maxvals, key)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/wimp.py", line 543, in keypress
    self._emit('click')
  File "/usr/lib/python3/dist-packages/urwid/widget.py", line 461, in _emit
    signals.emit_signal(self, name, self, *args)
  File "/usr/lib/python3/dist-packages/urwid/signals.py", line 265, in emit
    result |= self._call_callback(callback, user_arg, user_args, args)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/urwid/signals.py", line 295, in _call_callback
    return bool(callback(*args_to_pass))
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/bin/pijuice_cli.py", line 1994, in item_chosen
    callback()
  File "/usr/bin/pijuice_cli.py", line 1033, in __init__
    pijuice.config.SelectBatteryProfiles(current_fw_version)
    ^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'config'

etc

how does the software has been installed?

via diet-launcher, selected the software and install?

I guess it is one of the GPIO or interfaces group permissions needed to communicate with the HAT. Can you try:

usermod -aG i2c username

Replacing “username” with your unprivileged user, then, if it still does not work, repeat with gpio and spi instead of i2c. I’m currently not sure which interfaces are used but the HAT has multiple features, including an LCD, right?

@MichaIng it’s not about a specific user. It’s more that PiJuice is failing if it is executed as user root. At least that’s how I understood.

However its working using pijuice user like sudo -u pijuice pijuice_cli

1 Like

Oh right, then I have no idea. The service runs as pijuice user, but generally I see no reason why the root user (or any other specific user) should not have generally access to its API, or to trigger its functions directly, with sufficient GPIO access permissions. Especially I would expect a meaningful error message if root is not allowed to access the CLI or pijuice user required.

Does it work with the dietpi user?

sudo -u dietpi pijuice_cli

In case it really must be the pijuice user, we could add a shell alias for pijuice_cli to be wrapped with sudo -u dietpi automatically.

We btw just install the pijuice-base package from the RPi repo and a default config/template with a reboot user function added. That one should actually fail since it does not use sudo for the reboot :thinking:. However, this does not affect the CLI.