Что означает /bin/bash -c в сервисной единице?

Чтобы сделать автозапуск приложения во время перезагрузки.

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

Теперь мое приложение автозапускается во время перезагрузки.
Я хочу, чтобы мое приложение записывало всю выходную информацию в /var/log/app.log.
Вот что я делаю.
1.sudo touch /var/log/app.log
2. изменить только ExecStart.

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

Приложение может работать, но в /var/log/app.log не записывается журнал.
Root выполнит приложение.
Это доказательство здесь.

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

Почему root не имеет права писать лог в /var/log/app.log?

Чтобы изменить выражение ExecStart в

ExecStart=/bin/sh -c '/usr/bin/python /usr/local/bin/app   > /var/log/app.log 2>&1'  

Задача решена.
1.Почему root не имеет права писать логи в /var/log/app.log?
2.Что значит /bin/bash -c в сервисной единице?

3 ответа

Это не вопрос разрешений. Там просто нет оболочки, участвующей в выполнении ExecStart строка. Только команда и параметры, которые должны быть переданы этой команде, но ни перенаправления, ни трубопроводы, ни конкатенация с ; ни подстановка, ни любая другая функциональность оболочки. Таким образом, ваши "перенаправления" передаются в качестве параметров вашему приложению (только вы знаете, как ваше приложение справляется с этим).

Вы можете изменить это, вызвав оболочку и указав свою команду и перенаправления в виде командной строки для оболочки. Это то, что -c вариант делает.

Но подумайте, почему бы не использовать службы и ведение журналов, как это предусмотрено systemd: по умолчанию stdout и stderr модуля systemd отправляются в syslog. Вы можете настроить его с помощью StandardOutput= линия в вашем сервисе. Посмотри на man systemd.exec

ПРИМЕЧАНИЕ. Старый пост был написан в контексте исходного вопроса OP до редактирования, поэтому он неполный, но в контексте того, что было задано изначально, он все еще действителен.

Обновленный ответ:

Ключевой вопрос здесь заключается в том, что

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

Не работает оболочка, поэтому ваш > а также 2>&1 перенаправление не будет понято systemd.

Вот почему оболочка необходима для всей команды, чтобы перенаправление могло работать. Что касается -c флаг для оболочки, см. старую версию поста ниже.


СТАРЫЙ ПОСТ

-c флаг в обоих bash а также sh означает то же самое: выполнять команды, как указано в кавычках. Там нет большой загадки.

Ваше приложение, которое вы пытаетесь запустить, может иметь разное значение для флага -c, поэтому не думайте, что все флаги командной строки одинаковы для всех команд. Без документации для приложения трудно сказать, что должна делать опция.

Здесь потенциальная проблема заключается в том, что интерпретатор python примет -c в качестве своего собственного аргумента командной строки, а не приложения. Вероятно, это основная причина, по которой ваша команда терпит неудачу.

ExecStart=/usr/bin/python /usr/local/bin/app -c /etc/app.json должен быть в состоянии обработать вашу команду. Я проверил это с помощью небольшого скрипта:

$ 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

Лучший подход: скрипт должен быть выполнен с sudo chmod +x /usr/local/bin/app и используется сам по себе. То, как оно написано изначально, с / bin / sh, затем с python, затем вызов фактического скрипта является излишним. В примере моего тестового скрипта это было бы так:

$ 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

Остерегайтесь этого python ссылается на Python 2.7 в Ubuntu. Если вам нужно использовать Python3 специально, используйте вместо него / usr / bin / python3. Наиболее предпочтительный способ - приложение #!/usr/bin/env python или же #!/usr/bin/env python3 как первая строка

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 включить app.service

Для поиска журнала приложения с помощью команды журнала.

sudo journalctl  -u  app
Другие вопросы по тегам