5

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?

  • For future, please post complete commands to get proper answers. There is very big difference between your original post and what was edited later. We can only deal with questions that are clear and complete, and partial posts only lead to partially valid answers – Sergiy Kolodyazhnyy May 5 '17 at 0:14
2

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

ExecStart=/usr/bin/python /usr/local/bin/app   > /var/log/app.log 2>&1

Doesn't have shell running , so your > and 2>&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 both bash and sh 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:

$ cat test_script.py
import sys
print sys.argv[1],sys.argv[0]
$ python test_script.py this is a test                
this test_script.py

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:

$ cat test_script.py                                  
#!/usr/bin/env python
import sys
print sys.argv[1],sys.argv[0]
$ chmod +x test_script.py
$ ./test_script.py this is a test
this ./test_script.py

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.

| improve this answer | |
  • I rewrite post according to real environment, to make it more clear. – showkey May 4 '17 at 5:37
3

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 at man systemd.exec

| improve this answer | |
1

sudo vi /etc/systemd/system/app.service

[Unit]
Description=app
After=network.target

[Service]
ExecStart=/usr/bin/python /usr/local/bin/app  
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target

sudo systemctl daemon-reload
sudo systemctl enable app.service

To search app's log with journal command.

sudo journalctl  -u  app
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.