Permissions on /dev entries

I want to run a python script on a BPI M5 sbc to drive GPIO pins.

I can the script properly by doing sudo python3 test.py. When I try to run it without sudo I get "permission denied on /dev/gpiomem"

I can get this to work if I give read write permissions but this only works until the next bootup.

How can I make this permanent?

Note, I read somewhere that one can do this by creating a .rules file but for some reason I could not get this to work.

Any ideas?

1 Like

Welcome @xuraax to the community!

create a udev rule in /etc/udev/rules.d/

I made a rule, 50-myusb.rules
KERNEL=="ttyACM[0-9]*",MODE="0666"

This will set perms to ttyACM0..9 to 666 (default is 660)
reboot
verify ls -l /dev/ttyACM* is 666

1 Like

Thank you very much for your speedy reply. Your suggestion worked like a dream.

The content of my file was as follows:

KERNEL=="ttyS1",MODE="0666"
KERNEL=="gpiomem",MODE="0666"

Previously I had tried the following based on input from another forum:

filename was: /etc/udev/rules.d/mydevices.rules

Content was:
KERNEL=="gpiomem",NAME="%k", group ="gpio",MODE="0666"

This did not work for me on gpiomem. Any idea why please?

the group in /dev/tty* is dialout, do you have a diff group gpio ?

1 Like

Just another way is to elevate execution privileges. For example

  • use sudo command to run script/binary in question
  • chown by root and set suid bit for a binary (does not work for scripts)

Good luck!

1 Like

I have used those methods but they are rather tedious to use. Besides I have a problem to use sudo from Thonny IDE.

The .rules solution worked fine so I am happy.

Incidentally I would like to run my script (when finish) directly from power up. Can I use a .rules file to do this or is there a better method?

IMHO custom systemd unit will do.

2 Likes

Thank you for your suggestion to use systemd.

I was able to follow successfully the suggestion in the link you provided.

However when I tried to run my python script nothing appears to have happened. Maybe it is because mine is a command line application so I may need to add other stuff to get it to work.

1 Like

can you post the .service file, it is a few lines.

1 Like

The .service file remained exactly as in the link i.e.

[Unit]
Description=example systemd service unit file.

[Service]
ExecStart=/bin/bash /usr/sbin/example.sh

[Install]
WantedBy=multi-user.target

In the example.sh file I just added:

python3 ~/ECUhyo_BPI.py

In retrospect, should I have replaced the [Service] line with:
ExecStart=python3 ~/ECUhyo_BPI.py and done away with the example.sh file?

I will try this later on today.

Provided that service is executed automagically after system boot, it is safer to use full paths as for executable as for python script.

1 Like

In fact that is what I did when I eliminated the example.sh reference.

The line now is:
ExecStart=/bin/python3 /home/pi/ECUhyo_BPI.py

Besides sending text to a commandline screen my script also flashes an LED to signify functionality.

No characters are seen on the GUI but the LED does turn on and sometimes off which indicates that my script is attempting to run.

I suspect that there is a conflict between the messages sent to the command line screen and the GUI itself.

As far as I remember, Python's stdin and stdout behave far from obvious when scripts are being executed by cron and/or service. I use printing to file for debugging 'silent' scripts.

1 Like

I wish you could format the .service as code so it is easily readable. I don't have a BPI to test but can you share the python code (ECU.py)? I assume python3 is under /bin but in most systems python3 is under /usr/bin/

[Unit]
Description=example systemd service unit file.

[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi
ExecStart=/usr/bin/python3 ECU.py

[Install]
WantedBy=multi-user.target
1 Like

I am sorry I did not format the .service as code. I need to understand how to do this on this forum and will do so in the future. However note that what I posted was simply a cut and paste from the link provided by @ugnvs.

I can of course provide you with the code in my script but I fear it will probably confuse the issue more than help resolve it. My script is in fact a rewrite of a working script which I had written for the original rasperberry pi installed with TinyCore linux. It is a fairly lengthy piece of code and the current conversion is still not completely debugged.

Basically it picks up data coming in on the "rs232" gpio pin from a motorbike ECU, parses it and stores it in a .csv file for eventual offline analysis. Whilst running it sends some comments to a command line screen (if connected) but when on the bike a flashing led indicates that the script is still running and not stalled.

Where can I find how to properly attach code on this forum?

On reply, select the text you want to format and click on the 6th icon </> it will format the text as code (monospace) and thus easily readable.

I don't really want the script, I want to make sure it runs properly under systemd. You described what it does, my only suggestion is to use the command journalctl -xe to find out what's going on with the execution.

1 Like

Thanks for the advice.

In order to ensure that the failure to startup is not due to some bugs in my own code I created the following simple script which basically blinks an LED and also sends periodically some messages to the command line screen.

This was then placed in a test.service file.

At start up systemd invokes this command successfully since blinking starts taking place even before the Ubuntu MATE GUI comes up. At the left of the bottom status bar a message is displayed stating that Python3.8 is running. This eventually turns off.
However the messages in my code which I am sending to the command line screen do not appear and also I cannot do Cntrl+C to terminate my script.

It seems the issue is therefore of how to automatically open a terminal screen and how to direct my messages to this.

import RPi.GPIO as GPIO  
import time  
  
phyledpin = 11    # pin13, bcm27
 
def setup_board():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(phyledpin, GPIO.OUT)

def blink_board():
    while True:
        GPIO.output(phyledpin, GPIO.HIGH)
        print("********set phy pin ", phyledpin, " High********")
        time.sleep(0.5)  
        GPIO.output(phyledpin, GPIO.LOW)
        print("********set phy pin ", phyledpin, " Low********")
        time.sleep(0.5)

def shutdown():
    GPIO.cleanup()
  
if __name__ == '__main__':     # Program start  
    print('LED flashes at 0.5s interval')
    print('Press Ctrl-C to exit') 

    setup_board()
    print("Hardware information: ", GPIO.RPI_INFO)

try:  
    blink_board()
except KeyboardInterrupt:
    shutdown()

In [Service] can you add these lines and test again? systemd scripts do not usually write to screen but this trick may do ...

[Service]
StandardOutput=tty
TTYPath=/dev/tty1
1 Like

I inserted those 2 lines, first before the ExecStart line and then just after.

In the first trial my python script did not start at all.
In the second trial, my script started but then close after a few seconds.