Разница между systemd и программой запуска терминала

9

Мне любопытно, какова эта разница между программами; запускается с systemd при включении через systemctl, против тех, которые запускаются с помощью /etc/rc.localили через CLI.

Например, недавно я использовал shairport-sync для Raspberry Pi. Изначально я установил запуск shairport-sync с помощью sudo systemctl с включенным shairport-sync.

Позже я использовал функциональность shairport-syncдля запуска сценариев и публикации сообщений для подключения к устройствам.

К моему удивлению, сценарии , когда выполняется shairport-syncне kill arecordилиaplay

Тем не менее, когда я запускаю скрипт через терминал, скрипт выполняется и убивается arecordи aplay.

Чтобы еще больше запутать себя, я убил shairport-syncи запустил его через терминал, чтобы увидеть вывод происходящего. Когда я это сделал, скрипты работали так, как я ожидал, когда устройство подключалось и отключалось arecordи aplay. Так что , как исправить я отключил shairport-syncв sysmtectlи установить его для работы в /etc/rc.localкачестве быстрого решения. После того, как rebootон функционировал, как я ожидал.

Это наводит меня на мысль, что есть некоторая разница между программой, запускаемой отдельно, systemdи программой, которая запускается при запуске через /etc/rc.localCLI.

Почему это происходит? Это из-за разных уровней запуска? Немного темной магии?

Сценарий, который запускается при подключении устройства, shairport-syncвыглядит следующим образом:shairportstart.sh

#!/bin/sh
/usr/bin/sudo /bin/pkill arecord
if [ $(date +%H) -ge "18" -o $(date +%H) -le "7" ]; then
        /usr/bin/amixer set Speaker 40%
else
        /usr/bin/amixer set Speaker 100%
fi
/home/pi/shScripts/shairportfade.sh&

exit 0

Вот сценарий исчезновения: shairportfade.sh

#!/bin/sh
/usr/bin/amixer set Speaker 30-
for (( i=0; i<30; i++))
do  
    /usr/bin/amixer set Speaker 1+
done
exit 0

Сценарий, который запускается при отключении устройства, shairport-syncвыглядит следующим образом:shairportend.sh

#!/bin/sh
/usr/bin/amixer set Speaker 70%
/usr/bin/arecord -D plughw:1 -f dat | /usr/bin/aplay -D plughw:1 -f dat&
exit 0

Я обнаружил следующую ошибку /var/log/syslogтолько в том случае, если shairport-sync изначально запускался отдельно systemd. Когда shairport-syncзапускался из CLI или /etc/rc.localошибок не было.

Jan 24 00:38:45 raspberrypi shairport-sync[617]: sudo: no tty present and no askpass program specified

Обратите внимание, что единственная разница заключается в том, как shairport-syncизначально запускается, когда устройства подключаются или отключаются, shairport-syncпродолжает работать.

Бретт Рейнхард
источник
1
Этот ps ... awk ... grep ...материал может быть заменен более простымpkill
три
@ thrig изначально линия была намного проще, но так как она не работала или я думал, я пытался использовать другие методы, чтобы убить экземпляр, который все еще не работал. Убийство процесса само по себе не было проблемой, поскольку оно работало, но только при запуске из логина пользователя
Бретт Рейнхард
Вы можете показать список /home/pi/shScripts/shairportfade.sh?
Майкл Д.
@MichaelD. я добавил сценарий исчезновения, а также сценарий, который выполняется, когда устройство отключается от синхронизации shairport
Бретт Рейнхард,
@BrettReinhard, в чем проблема с запуском сценарияrc.local
Майкл Д.

Ответы:

18

Вариации "Почему вещи ведут себя по-разному в systemd?" часто задаваемый вопрос

Каждый раз, когда что-то запускается из CLI, а не из systemd, есть несколько широких категорий возможностей для учета различий.

  1. Различные переменные среды . systemdдокументирует переменные окружения, которые он передает, в man systemd.execразделе Переменные окружения в порожденных процессах . Если вы хотите проверить разницу самостоятельно, вы можете использовать ее systemd-run /path/to/binary, она будет запускать ваше приложение во временной области, как если бы оно выполнялось службой systemd. Вы получите выход , как: Running as unit: run-u160.service. Затем вы можете journalctl -u run-u160.serviceпросмотреть вывод. Измените ваше приложение, чтобы выгрузить полученные переменные среды, и сравните запуск CLI с запуском systemd. Если приложение не было удобно модифицировано, вы можете просто использовать, systemd-run envчтобы увидеть переменные среды, которые будут переданы, и просмотреть итоговую запись в журнале. Если вы пытаетесь запустить приложение X11 GUI, DISPLAYнеобходимо установить переменную среды, В этом случае рассмотрите возможность использования функции автозапуска вашего рабочего стола вместо systemd.
  2. Ресурсные ограничения . Смотрите man systemd.resource-controlзначения конфигурации, которые могут ограничить потребление ресурсов. Используйте systemctl show your-unit-unit.serviceдля проверки полных значений конфигурации, влияющих на службу, которую вы пытаетесь запустить.
  3. Неинтерактивная оболочка . Ваша bashсреда CLI представляет собой интерактивную оболочку входа в систему . Он получил файлы, как .bashrcэто systemdне имеет. Помимо установки переменных среды, эти сценарии могут выполнять множество других действий, таких как подключение агента SSH, чтобы действия SSH не требовали входа в систему. См. Также Разница между Оболочкой входа в систему и Оболочкой без регистрации?
  4. Нет TTY . Ваш интерактивный сеанс подключен к TTY, который некоторые программы любят sudoи sshожидают при запросе паролей. Смотрите также sudo: tty отсутствует и не задана программа askpass
  5. Относительные и Абсолютные Пути . Относительная двоичная работа в оболочке, но, какman systemd.service указано в документе , первым аргументом ExecStart=должен быть абсолютный путь к двоичному файлу.
  6. Ограниченный синтаксис командной строки . Интерфейсы systemdкомандной строки оболочки поддерживают множество метасимволов, но имеют очень ограниченный синтаксис командной строки . В зависимости от ваших потребностей, вы сможете реплицировать синтаксис оболочки с systemdпомощью явного запуска вашей команды через оболочку:ExecStart=/bin/bash -c '/my/bash $(syntax) >/goes-here.txt'

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

Марк Стосберг
источник
Кроме того, необходимо принимать во внимание MAC контекста (SELinux, ...), возможности пространств имен ...
Бигон
2
@BrettReinhard Не вызывайте sudoсценарий оболочки, лучше запускаемый sudo shairportstart.shиз терминала, так как systemd запускает сценарий от имени пользователя root, нет необходимости использовать sudo от имени пользователя root.
Майкл Д.
1
Я решил свою проблему несколькими способами, пытаясь понять, что происходит. В конечном итоге я изменил команду kill на /usr/bin/echo "mypassword" | /usr/bin/sudo /bin/pkill arecord. Позже сегодня я попытаюсь удалить команды sudoand из echoмоей команды kill и посмотреть, даст ли это те же результаты. Я предполагаю, что это будет работать, так как кажется, что ошибка была вызвана тем, что пароль не был отправлен с sudoкомандой. Спасибо за помощь в понимании того, почему есть разница между systemdCLI
Бретт Рейнхард
1
Еще одно отличие, которое может быть очевидным, но которое меня сегодня укусило, заключается в том, что systemd пытается отслеживать состояние службы и не запускает ее, если считает, что она уже активна, поэтому он может даже не запустить скрипт init.d, если он думает, что сервис работает. Напротив, сценарии init.d обычно пишутся так, чтобы всегда проверять и пытаться запустить службу соответствующим образом.
Джош Келли
1
@JoshKelley Спасибо за совет. Это не разница между systemd и CLI, а между сценариями systemd и sysVinit init.d.
Марк Стосберг