Raspberry Pi – using GPIO / WiringPi without root (sudo) access

Posted: 2013/10/21 in Development, Linux

Just needing to get this down quickly and succinctly…

The Raspberry Pi is super-fun for me as it’s a full OS (Linux, which I really like a lot) with Pins!  Current project: make a (private) website that will let me open/close and check my garage door.  Maybe more on this later.

SUPER frustrating is the inability for a web-server to control the GPIO pins on my Raspberry Pi because the web-server is not running as root.  Really?!?  The only way to address the GPIO pins of the Pi is as sudo / root?!?  I can’t really complain all that much because I’m not willing to learn and write the C code required for this to happen.  So I searched and tried and iterated and eventually ended up running shell commands from within the web-server scripts because the awesome computer interface programmer Gordon Henderson made a command-line utility (gpio) that WILL write to the GPIO pins without being root.

On the RaspberryPi.org site, Gordon has a nice post of how he setup his Raspberry Pi so that his programs can read/write to the GPIO pins without being root.  I only need the no-root part.  Gordon’s method almost worked for me.  Here’s what I ended up doing.

MODIFIED 2016 May 1

Per some GREAT insights and suggestions in the comments, I have updated this Alexander (comment on 2016/02/08 at 12:45 pm below) who identified that, on newer versions of Raspbian (I’m using Jessie at the moment), that the location of the GPIO pins has moved (from /sys/devices/virtual/gpio/gpio${pin} to /sys/class/gpio/gpio${pin} — if you get errors with the script below, try going back to /sys/devices/virtual/gpio/…).

Here, now, is an updated version of this script…

 

MODIFIED 2016 May 8

Came across this StackExchange article by Karl Easterly on what to do when getting “No access to /dev/mem.  Try running as root!” error in Python.  In short, RPi.GPIO cannot access what it needs without having additional permissions.  The article does a great job explaining why the current approach (used below) is better than running Python as root, but still not great. Bummer. See last line of set_gpio_pins.sh for Karl’s solution, but modified to use my particular use-case where the ‘user’ running the Python scripts is www-data (this took me some trial-and-error to figure out.

1) Create a script that “exports” specific GPIO pins and then sets the ownership.

cat /usr/local/bin/set_gpio_pins.sh

#!/bin/bash
# filename: /usr/local/bin/set_gpio_pins.sh << set as executable (chmod +x)
#
# set GPIO pins 17, 22, and 24 to be usable without root access
#  In fact, make them accessible to the web-server (www-data) and
#   the 'typical' user (pi).  The 'chmod' allows user 'pi' to write
# This script must be run as root (sudo), in root's crontab, or
#   each of the lines in the for-loop need to start with 'sudo'
for pin in 17 22 24; do
   /usr/bin/env gpio export ${pin} out
   chown -R www-data:pi /sys/class/gpio/gpio${pin}
   chmod -R g+w /sys/class/gpio/gpio${pin}
done

# Karl's solution, slightly modified
chown root:www-data /dev/gpiomem
chmod g+rw /dev/gpiomem

 

2) Set the file to be executable

sudo chmod +x /usr/local/bin/set_gpio_pins.sh

 

3) Instead of using /etc/rc.local, I added the running of this script as a cron-job so that it runs on boot-up.  Starting with ‘sudo’ means this is the crontab for the root/superuser (hence, no need for ‘sudo’ in the set_gpio_pins.sh script).  The “-e” brings up the editor.

sudo crontab -e
# at end of file add...
@reboot      /usr/local/bin/set_gpio_pins.sh  # file from step #1 above

 

FINALLY! I can use the pins, inside of scripts (ex. Python or PHP or ____), without having to have the webserver run as root nor using shell-commands inside a script. Whew.

Advertisements
Comments
  1. GIGI says:

    You can use php WiringPi though

    • GIGI,

      Yeah, I could use PHP. But I’m wanting to use the Pi for a lot of other tasks concurrently. Loading PHP on each web-request seemed like a lot of bloat, so I went with Python.

      Regardless, if the web-server not is running as root, the pins are not directly accessible without ‘setting’ them as not-needing-root. Hence this blog post.

      I do love PHP, though! Maybe some day…

      Thanks for the idea, though.

  2. tariquesani says:

    Hi,

    I tried this on a new Raspberry Pi 2 and I get

    chown: cannot access `/sys/devices/virtual/gpio/gpio17′: No such file or directory
    chmod: cannot access `/sys/devices/virtual/gpio/gpio17′: No such file or directory
    chown: cannot access `/sys/devices/virtual/gpio/gpio22′: No such file or directory
    chmod: cannot access `/sys/devices/virtual/gpio/gpio22′: No such file or directory
    chown: cannot access `/sys/devices/virtual/gpio/gpio24′: No such file or directory
    chmod: cannot access `/sys/devices/virtual/gpio/gpio24′: No such file or directory

    Can you please help…

  3. foo says:

    I can confirm that this is even working for the Raspberry Pi 2!

  4. alborz says:

    Would have been awesome if this worked but I am getting the same error as the guy above:

    chown: cannot access ‘/sys/devices/virtual/gpio/gpio22’: No such file or directory
    chmod: cannot access ‘/sys/devices/virtual/gpio/gpio22’: No such file or directory
    chown: cannot access ‘/sys/devices/virtual/gpio/gpio24’: No such file or directory
    chmod: cannot access ‘/sys/devices/virtual/gpio/gpio24’: No such file or directory

  5. Alexander says:

    I suggest trying to change /sys/devices/virtual/gpio/gpio$pin to /sys/class/gpio/gpio$pin in the script.

  6. Derek says:

    If I run the script, even as root I get.

    chmod: changing permissions of `/sys/class/gpio/gpio22/direction’: Operation not permitted

    • Derek – I’m not sure why the word ‘direction’ is involved… perhaps that word has been accidentally added to your script? Also, please see if the updated version of this page (2016 May 1) works better for you.

  7. Jordi says:

    Thank you Alexander. It worked for me too on RPi 2 with Raspbian Wheezy.

  8. 433 says:

    I can’t get this to work. I’m using a program called “rfoutlet” which relies on wiringPi and it works from the command line with sudo but when I use a script or try to trigger it from openhab I need to authenticate. Other scripts don’t need sudo cause I’ve edited sudoers to allow scripts from this user/group. WiringPi still says it needs sudo – so I tried your solution but wiringPi still thinks it needs sudo and I have no idea what to try next. I’ve tried a lot of different things and your post is the closest to a solution I’ve found but it seems like wiringPi doesn’t understand that the gpio pins are available without sudo even after changing this. I’ve also tried solutions from the developer of wiringPi but that didn’t work either. I’ve followed different tutorials for different applications such as rfoutlet and rcswitch that both rely on wiringPi but none are able to run without sudo from command line or via openhab. I can control my 433mhz switches via rfoutlet’s PHP-toggle page though but my goal is to be able to switch from within openhab.

    Ideas – anyone reading this?

    • 433,
      A couple of things come to mind:

      1) You write “WiringPi still says it needs sudo…” Is that to mean that this post is not working for you even on the command-line, using commands? Perhaps you can walk us through what you’ve tried in this regard?

      2) Do you now what operating system you have on the Raspberry Pi you are working on? One way to figure this out is to run – from the command-line/terminal on the Raspberry Pi: cat /etc/os-release And if that does not seem to work quite-right, you can do a more catch-all by running: cat /etc/*-release. This will help with future trouble-shooting if/as needed.

      3) Are you sure that you are setting up input/output/whatever correctly… to what you are wanting/expecting? That is, in the ‘for’ loop of this post’s example, there is a line that looks like this: /usr/bin/env gpio export ${pin} out. If you are needing one/some pin(s) to be an input, for example, then you’d have to setup another loop with the last word being “in”: /usr/bin/env gpio export ${pin} in. The wiringPi site has more on how these settings all work.

      4) I don’t know C very well so I don’t fully understand what “rfoutlet” is doing in its executables. Perhaps rfoutlet is trying to set the pins as input/output/whatever after you have already done so using the script in this post? And upon doing so, is perhaps setting the group or user or permissions incorrectly? For example, this particular post attempts to keep the pins rather locked down, such that only the user “root” and anyone in the group “www-data” can use the pins. This is (should be? haha) standard procedure (limiting use), so perhaps the rfoutlet author is doing the same, but in a way that causes problems when using openhab?

      5) One more idea, in the last line of the ‘for’ loops in the script of this post, try replacing chmod -R g+w /sys/class/gpio/gpio${pin} with chmod -R a+w /sys/class/gpio/gpio${pin} – the difference being that I replaced “g+w” with “a+w”. This has the effect of making any user, program, etc. able to access the pins, not just the user and/or anyone in the group (example from the post, group “www-data”).

      If you would, reply back and let us know what you find? Reporting any/all errors – if possible – would be great!

      • 433 says:

        I’m on jessie on a rpi2 for this project. I have 5 pi’s so I’m not completely new to this but sometimes when you hit a bump in the road it’s easy to get frustrated. Turns out more people had the same problem. I followed this tutorial and actually got it to work now https://www.samkear.com/hardware/control-power-outlets-wirelessly-raspberry-pi

        Seems like wiringPi asks for sudo even though it doesn’t need to. So I made sure to remove all sudo’s from openhab exec bindings. I also removed sudo from my scripts that I use to send my commands (so that I can send 5 commands at once to lower the risk of loss). But I looked in so many places and had everything set properly.

        My user/group was allowed to run scripts without sudo it’s just that wiringPi didn’t seem to understand that, even though it resides in the correct spot and has the right permissions. The missing piece was that I changed the codesend owner to root:root instead of openhab:openhab. And finally setting 4755 to codesend – thereby making it look like a root run program even though my user openhab runs it. This in turn seems to fool wiringPi so that it doesn’t halt the process 🙂 I had never used the setuid permission before so this was really interesting and useful. The tutorial mentions this but didn’t explain why – so I had to find out the hard way by spending a great deal of time on it. Still fun to troubleshoot as long as you eventually solve the problem. I appreciate your time to reply and I had already tried a lot of the things posted here and on other places where people struggle with this same issue. But for me this was the magic trick with setuid – so if someone else comes here with that problem give it a go.

        Thanks for your time!

  9. Qinru says:

    Hi, David

    When I typed “cat /usr/local/bin/set_gpio_pins.sh” in the terminal, I get error saying “cat /usr/local/bin/set_gpio_pins.sh: No such file or directory”?
    I cannot create such file and follow the rest of the instructions. Do you know where the problem is? I am using Rpi 2.

  10. Nelson says:

    Hi David, thanks for your detailed description. I still had some problems to access GPIOs without root. After some research I found the following link: http://www.netzmafia.de/skripten/hardware/RasPi/RasPi_GPIO_Shell.html which solved the problem. It’s in german, but the main things (as shell commands or new rules file are understandable). I created exactly the file 80-gpio-noroot.rules in the mentioned directory with root and the restricted user (no su/sudo) could access the GPIO Pins from Python / Bash without any problems.
    May be it helps someone.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s