51

I've created a new service for a Python script that works when running standalone but gives errors below when run through systemd :

Oct 02 12:17:09 raspberrypi systemd[1]: Started Read pressure And Post to mqtt.
Oct 02 12:17:09 raspberrypi systemd[1]: ReadPressure.service: Main process exited, code=exited, status=203/EXEC
Oct 02 12:17:09 raspberrypi systemd[1]: ReadPressure.service: Unit entered failed state.
Oct 02 12:17:09 raspberrypi systemd[1]: ReadPressure.service: Failed with result 'exit-code'.
Oct 02 12:17:09 raspberrypi systemd[1]: ReadPressure.service: Service hold-off time over, scheduling restart.
Oct 02 12:17:09 raspberrypi systemd[1]: Stopped Read pressure And Post to mqtt.
Oct 02 12:17:09 raspberrypi systemd[1]: ReadPressure.service: Start request repeated too quickly.
Oct 02 12:17:09 raspberrypi systemd[1]: Failed to start Read pressure And Post to mqtt.
Oct 02 12:17:09 raspberrypi systemd[1]: ReadPressure.service: Unit entered failed state.
Oct 02 12:17:09 raspberrypi systemd[1]: ReadPressure.service: Failed with result 'exit-code'.

The service was created in "etc/systemd/system/ReadPressure.service. it has executable rights.

The services looks like :

[Unit]
Description=ReadPressure

[Service]
ExecStart=/bin/bash -c 'python3 -u /home/pi/ReadPressure/ReadPressure2AndPostToMqtt.py'
WorkingDirectory=/home/pi/ReadPressure/
Restart=always
User=pi

[Install]
WantedBy=multi-user.target

Any ideas why im getting the errors? The operating system is Raspbian.

Thanks

  • A related question is https://unix.stackexchange.com/questions/458648/ . – JdeBP Oct 03 '18 at 11:11
  • 5
    Why are you starting a bash that is calling python? You can start python directly with ExecStart=/usr/bin/python3... or wherever your python3 binary resides. – Thomas Oct 03 '18 at 11:18
  • Tried starting directly too. I saw a example like that so i tried it to see if it gives me different results. – resolver101 Oct 03 '18 at 11:37
  • 1
    according to hte docmentation "203 EXIT_EXEC" says "The actual process execution failed (specifically, the execve(2) system call). Most likely this is caused by a missing or non-accessible executable file." I guess it cant find the python file? in the log it says " Started Read pressure And Post to mqtt" but the file is named "ReadPressure2AndPostToMqtt.py". Do you think that could be part of the problem? i dont know how to correct it, any ideas? – resolver101 Oct 03 '18 at 11:39
  • What does type python3 return? – Thomas Oct 03 '18 at 12:10
  • Can you execute the file as the user pi? To verify that, try su pi and then just try your command: /usr/bin/python3 -u /home/pi/ReadPressure/ReadPressure2AndPostToMqtt.py. Don't forget to exit or you'll remain in that environment, which may cause confusion. Also, make sure to also use absolute paths to the executeables. – rudib Oct 03 '18 at 12:50
  • "type python3" returns "python3 is /usr/bin/python3" – resolver101 Oct 03 '18 at 13:18
  • ran "su pi" and "/usr/bin/python3 -u /home/pi/ReadPressure/ReadPressure2AndPostToMqtt.py" works fine. – resolver101 Oct 03 '18 at 13:32
  • Please see the FAQ about why things work differently under systemd: https://unix.stackexchange.com/a/339645/20239 – Mark Stosberg Oct 03 '18 at 14:46
  • Got it working. it was the log file name, change it from "ReadPressure2AndPostToMqtt.py" to "ReadPressure2". – resolver101 Oct 03 '18 at 15:34
  • @resolver101 what does it mean the "log file name"? what log? – robertspierre Aug 20 '22 at 08:47

7 Answers7

49

Try:

pi@raspberrypi:~ $ systemctl status ReadPressure.service

Paraphrasing @Ingo from I fail to start a python program in Thonny on startup

The error message (code=exited, status=203/EXEC) is often seen when the script itself or its interpreter cannot be executed.

It could have these reasons:

  • wrong path to script (e.g. /home/py/ReadPressure2AndPostToMqtt.py)

  • script not executable

  • no shebang (first line)

  • wrong path in shebang (e.g. /bin/python3)

  • internal files in your script might be missing access permissions.

  • SELinux may be preventing execution of the ExecStart parameter; check /var/log/audit/audit.log for messages of the form: type=AVC msg=audit([...]): avc: denied { execute } or in the output of ausearch -ts recent -m avc -i.

  • You have the wrong WorkingDirectory parameter

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
15

Another possible reason for status=203/EXEC might be SELinux. In my case I had a unit file that launched a python script:

[Unit]
Description=LibreNMS SNMP Poller Service
After=network.target

[Service] ExecStart=/opt/librenms/librenms-service.py -v -d ExecReload=/bin/kill -HUP $MAINPID WorkingDirectory=/opt/librenms User=librenms Group=librenms RestartSec=10 Restart=always

[Install] WantedBy=multi-user.target

The python script had SELinux type descriptor httpd_sys_content_t, which was not allowed to be executed. I saw the error by using audit2why < /var/log/audit/audit.log which looked like

type=AVC msg=audit(1631272189.992:1032): avc:  denied  { execute } for  pid=2873 comm="(rvice.py)" name="librenms-service.py" dev="sda3" ino=714393 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=file permissive=0
    Was caused by:
            Missing type enforcement (TE) allow rule.

            You can use audit2allow to generate a loadable module to allow this access.

I ended up editing the Security context.

Non permanent edit (for testing):

chcon -t bin_t /opt/librenms/librenms-service.py

Permanent edit:

semanage fcontext -a -t bin_t '/opt/librenms/librenms-service.py'
restorecon -Fv /opt/bin/librenms-service.py
  • "chcon -t bin_t" did it for me. Is there any reason you call it a "non-permanent" solution? – Eliezer Miron Mar 17 '22 at 17:22
  • chcon will label the file until a relabeling will occur (upgrades). The permanent solution is using semanage and then relabel manually with restorecon – Orsiris de Jong Mar 18 '22 at 18:55
  • I assume that "relabeling" is not something that happens for user-created services, by default? – Eliezer Miron Mar 21 '22 at 18:47
  • 1
    Since there are default lables for every default directory, files in /opt will inherit from default /opt label. So your user created service will be relabeled on upgrades. – Orsiris de Jong Mar 22 '22 at 09:39
7

You may need to quote your command, e.g.:

ExecStart="/bin/bash -c 'python3 bla blah'"
user1794469
  • 4,067
  • 1
  • 26
  • 42
Anne Bennett
  • 71
  • 1
  • 1
3

In my case I got the following error: ... /usr/bin/env: 'python3\r': No such file or directory based on the shebang:

#!/usr/bin/env python3

Took me some time to notice the Carriage return '\r'. After deleting it everything worked fine.

1

For me, the issue was actually a previous service of the same name I had tried to install earlier. I could tell that that was the issue by the references to the old service in the log. Removing the old service and running 'systemctl daemon-reload' fixed the issue for me.

1

In my case the bash script to start was on a different physical drive than the one in which the system resides.

Putting the script under /usr/local/bin fixed the issue, although I'm not sure why.

  • you system can prevent execution of system service from some directories https://serverfault.com/questions/957084/failed-at-step-exec-spawning-permission-denied – Daniel Mar 08 '23 at 02:24
0

I had the error when the binary belong to a root user with permission 700 e.g. hadn't execution permission for others. The service unit use own user so it can't start the service. I made chown o+x /sbin/my_service and it worked after this. Just wondered that nothing meaningful was written to logs I had to guess. Maybe systemd needs for some debug flag, if anyone know please let me know.