Search code examples
pythonlinuxsystemdpython-keyring

Unable to use Python keyring module from systemd service


I want a python script to automatically start after boot on a linux computer. To achieve this I set up a systemd service:

[Unit]
Description=My Script Service
Wants=network-online.target
After=network-online.target
After=multi-user.target
StartLimitIntervalSec=3600
StartLimitBurst=60

[Service]
Type=idle
User=masterofpuppets
Restart=on-failure
RestartSec=60s
WorkingDirectory=/home/masterofpuppets
ExecStart=/home/masterofpuppets/mypythonscript.py

[Install]
WantedBy=multi-user.target

But I get an error:

sudo systemctl status mysystemd.service
● transfer_DB_remote_to_local.service - My Script Service
     Loaded: loaded (/etc/systemd/system/mysystemd.service; enabled; vendor preset: enabled)
     Active: activating (auto-restart) (Result: exit-code) since Mon 2022-11-21 11:49:46 CET; 55s ago
    Process: 19283 ExecStart=/home/masterofpuppets/mypythonscript.py (code=exited, status=1/FAILURE)
   Main PID: 19283 (code=exited, status=1/FAILURE)

The python script is

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import subprocess
import keyring
import time

DB_backup_from_server = f"mysqldump --single-transaction --quick -v -h 192.168.0.97 -u {keyring.get_password('serverDB', 'user')} -p'{keyring.get_password('serverDB', 'pw')}' testDB > ~/testDB_backup.sql"
restore_backup_to_local_DB = f"mysql -v -u {keyring.get_password('mysqlDB', 'user')} -p'{keyring.get_password('mysqlDB', 'pw')}' testDB < ~/testDB_backup.sql"

commands = [DB_backup_from_server, restore_backup_to_local_DB]

execution_interval = 60*60
t0 = time.time() - execution_interval
while True:
    if time.time() - t0 > execution_interval:
        t0 = time.time()
        for cmd in commands:
            subprocess.run(cmd, 
                            stdout = subprocess.PIPE, 
                            universal_newlines = True,
                            shell = True)
    time.sleep(60)

There are no errors if I start it manually.

This is a similar issue, but the suggested solution doesn't help in my case.

Edit:

journalctl -u mysystemd.service
Nov 21 14:36:37 masterofpuppets-pc systemd[1]: Started My Script Service.
Nov 21 14:36:38 masterofpuppets-pc mypythonscript.py[47110]: Traceback (most recent call last):
Nov 21 14:36:38 masterofpuppets-pc mypythonscript.py[47110]:   File "/home/masterofpuppets/mypythonscript.py
Nov 21 14:36:38 masterofpuppets-pc mypythonscript.py[47110]:     DB_backup_from_server = f"mysqldump --single-transaction --quick -v -h 192.168.0.38 -u {keyring.get_>
Nov 21 14:36:38 masterofpuppets-pc mypythonscript.py[47110]:   File "/usr/lib/python3/dist-packages/keyring/core.py", line 57, in get_password
Nov 21 14:36:38 masterofpuppets-pc mypythonscript.py[47110]:     return _keyring_backend.get_password(service_name, username)
Nov 21 14:36:38 masterofpuppets-pc mypythonscript.py[47110]:   File "/usr/lib/python3/dist-packages/keyring/backends/fail.py", line 25, in get_password
Nov 21 14:36:38 masterofpuppets-pc mypythonscript.py[47110]:     raise NoKeyringError(msg)
Nov 21 14:36:38 masterofpuppets-pc mypythonscript.py[47110]: keyring.errors.NoKeyringError: No recommended backend was available. Install a recommended 3rd party bac>
Nov 21 14:36:38 masterofpuppets-pc systemd[1]: mysystemd.service: Main process exited, code=exited, status=1/FAILURE
Nov 21 14:36:38 masterofpuppets-pc systemd[1]: mysystemd.service: Failed with result 'exit-code'.
Nov 21 14:37:38 masterofpuppets-pc systemd[1]: mysystemd.service: Scheduled restart job, restart counter is at 143.
Nov 21 14:37:38 masterofpuppets-pc systemd[1]: Stopped My Script Service.

Solution

  • Thanks to the hints, I now got it working via a user unit service. The file is located at ~/.config/systemd/user/myuserunit.service

    [Unit]
    StartLimitIntervalSec=3600
    StartLimitBurst=60
    
    [Service]
    Type=simple
    Restart=on-failure
    RestartSec=60s
    ExecStart=/home/masterofpuppets/mypythonscript.py
    
    [Install]
    WantedBy=default.target
    

    enabling the service

    systemctl --user daemon-reload
    systemctl --user enable myuserunit.service 
    

    Now it automatically starts after reboot/login.