To make my app autorun during reboot.
sudo vi /etc/systemd/system/app.service
[Unit]
Description=app
After=network.target
[Service]
ExecStart=/usr/bin/python /usr/local/bin/app
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable app.service
Now my app autorun during reboot.
I want to make my app write all output info into /var/log/app.log.
Here is what i do.
1.sudo touch /var/log/app.log
2. to change ExecStart only.
ExecStart=/usr/bin/python /usr/local/bin/app > /var/log/app.log 2>&1
App can run but no log written into /var/log/app.log.
Root will execute the app.
It's proof here.
ps aux|grep app
root 246 0.0 3.8 56052 10056 ? Ss 00:57 0:00 /usr/bin/python /usr/local/bin/app > /var/log/app.log 2>&1
Why root has no permission to write log into /var/log/app.log?
To change ExecStart statement into
ExecStart=/bin/sh -c '/usr/bin/python /usr/local/bin/app > /var/log/app.log 2>&1'
Problem solved.
1.Why root no permission to write log into /var/log/app.log?
2.What does /bin/bash -c mean in service unit?
It's not a matter of permissions. There is simply no shell involved in executing the
ExecStart
string. Only a command and the options to be passed to that command, but neither redirections nor piping nor concatening with;
nor substitution or any other shell functionality. Thus, your "redirections" are passed as options to your app (only you know how your app handles this).You can change this by calling a shell and giving your command and redirections as command string to the shell. This is what the
-c
option does.But think about why not use the services and logging as intended by systemd: By default stdout and stderr of a systemd unit are sent to syslog. You can configure it with the
StandardOutput=
line in your service. Have a look atman systemd.exec
NOTE: The old post was written in the context of OP's original question, before edit, so it is incomplete but in the context of what was originally was asked, it's still valid.
Updated answer:
The key issue here is that
Doesn't have shell running , so your
>
and2>&1
redirection won't be understood by systemd.That's why shell is necessary around the whole command so that redirection can work. As for
-c
flag for shell, see the old version of the post below.OLD POST
The
-c
flag in bothbash
andsh
mean same thing: execute commands as provided within the quotes. There's no great mystery.Your app that you're trying to run might have different meaning for -c flag, so don't assume all command-line flags are the same for all commands. Without documentation for the app, it's hard to tell what an option is supposed to do.
Potential issue here is that python interpreter will assume -c as its own command-line argument, not to the app. Probably that's the main reason your command fails.The
ExecStart=/usr/bin/python /usr/local/bin/app -c /etc/app.json
should be able to process your command. I've tested it with a small script:Better approach: a script should be made executable with
sudo chmod +x /usr/local/bin/app
and used by itself. The way it is written originally, with /bin/sh, then python, then calling actual script is kind of redundant. In the example of my test script that would be like so:Beware that
python
refers to Python 2.7 on Ubuntu. If you need to use Python3 specifically, use /usr/bin/python3 instead. Most preferred way is for the app to have#!/usr/bin/env python
or#!/usr/bin/env python3
as first line.sudo vi /etc/systemd/system/app.service
sudo systemctl daemon-reload
sudo systemctl enable app.service
To search app's log with journal command.