How to run a command inside a virtualenv using systemd
This doesn't work because source
is a shell command, so systemd's ExecStart=
or ExecStartPre=
won't understand them directly... (BTW, the same is true for cd
and the &&
.)
You could achieve that by running a shell explicitly and running all your commands together there:
ExecStart=/bin/sh -c 'cd /home/debian/ap/ && source venv-ap/bin/activate && crossbar start'
But a better approach is, instead of sourcing the "activate" script, to use the python
executable in the bin/
of your virtualenv directly.
If you look at virtualenv's usage document, you'll notice it says:
ENV/bin
is created, where executables live - noticeably a new python. Thus running a script with#! /path/to/ENV/bin/python
would run that script under this virtualenv’s python.
In other words, assuming crossbar
is the Python script you want to run that requires the venv-ap
virtualenv, simply begin crossbar
with:
#!/home/debian/ap/venv-ap/bin/python
And it will automatically use the virtualenv whenever invoked.
Also possible, invoking the Python interpreter from the virtualenv directly, with:
ExecStart=/home/debian/ap/venv-ap/bin/python /path/to/crossbar start
(Also, regarding running in a specific directory, setting WorkingDirectory=/home/debian/ap
is better than using a cd
command. You don't need a shell that way, and systemd can do better error handling for you.)
Related videos on Youtube
sscirrus
Updated on September 18, 2022Comments
-
sscirrus over 1 year
I believe this should be simple but I can't get it to work properly.
These are the commands I can run on command line:
cd /home/debian/ap # Start a virtualenv source venv-ap/bin/activate # This needs to happen inside the virtualenv and takes ~20 seconds crossbar start # Outside the virtualenv, perhaps in a different command line window python3 /home/debian/myscript.py
These commands have to be done in this order. Due to the virtualenv, the non-executable for crossbar, and the separate python script afterwards, I haven't been able to figure out the best way to get this to work. My current work-in-progress:
[Unit] Description=Start CB After=network.target [Service] Type=simple User=debian ExecStartPre=source /home/debian/ap/venv-ap/bin/activate ExecStart=cd /home/debian/ap/ && crossbar start Restart=always [Install] WantedBy=multi-user.target
-
Admin almost 6 yearsCould you solve it yet? If so, how?
-
-
nerdoc about 3 yearsBut, the
.venv/bin/activate
script does more than setting the interpreter. E.g. installing packages does not work. `/path/to(venv/python -m pip install django" does not what it should. -
filbranden about 3 years@nerdoc I haven't tested it myself... The venv docs call out usage without activating explicitly: "You don’t specifically need to activate an environment; activation just prepends the virtual environment’s binary directory to your path, so that “python” invokes the virtual environment’s Python interpreter and you can run installed scripts without having to use their full path. However, all scripts installed in a virtual environment should be runnable without activating it, and run with the virtual environment’s Python automatically."