Что означает /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