LINUX.ORG.RU

Управление сервисом из программы на C/C++

 , , ,


0

1

Представим, что нужно из программы, запущенной с нужными привилегиями, управлять службой systemd/upstart/etc. Как это правильно делать?

Понятно, что в общем случае всегда поможет exec("/sbin/service xxx restart"); (или соответствующий аналог), но хотелось бы какие-то сишные интерфейсы, без system и exec.

Больше остальных интересует systemd, с высокой вероятностью кроме него поддерживать ничего не нужно будет. Нашел описание интерфейса D-Bus к нему. Но из исходников systemctl я выяснил, что он работает не через D-Bus, а через какой-то свой сокет, либо через kdbus. Я так понял, что это внутренняя шина, и лучше ей не пользоваться. Короче, что правильно использовать, D-Bus, system(), или может есть какие-то другие пути?

В целях самообразования интересно также, есть ли какой-то подобный интерфейс у upstart?

UPD. DBus интерфейс для Upstart тоже есть, и более того, он является предпочитаемым с точки зрения разработчиков Upstart.

★★★

Последнее исправление: Kiborg (всего исправлений: 1)

но хотелось бы какие-то сишные интерфейсы, без system и exec.

Во-первых, system(3) - это сишный интерфейс.

Во-вторых, запуск «service xxx restart» - самый простой, надежный и портабельный способ сделать то, что ты хочешь

annulen ★★★★★
()

Представим, что нужно из программы, запущенной с нужными привилегиями, управлять службой systemd/upstart/etc. Как это правильно делать?

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

emulek
()
Ответ на: комментарий от annulen

Это всё понятно, сейчас так и работает. Вопрос пока интересует несколько с теоретической точки зрения: как было бы правильно делать. Моё имхо считает, что должен быть какой-то интерфейс типа библиотеки (в случае с systemd сейчас это libdbus-1.so, т. е. уже что-то), а не банальный exec.

Kiborg ★★★
() автор топика
Ответ на: комментарий от emulek

У меня не сервис, а штука, которая должна переконфигурировать сеть и применить изменения, т. е. по сути сделать service network restart.

Kiborg ★★★
() автор топика
Ответ на: комментарий от annulen

Простой, ограниченно портабельный, но совершенно ненадежный. Для скрипта сойдет, но в программе на C++ уровень интеграции должен быть выше.

asaw ★★★★★
()
Ответ на: комментарий от asaw

но совершенно ненадежный

Возврат нуля гарантирует успешность завершения операции, куда надежнее.

но в программе на C++ уровень интеграции должен быть выше.

Никому он ничего не должен, юникс-вэй во все поля.

В С++ вообще отсутствуют «нативные» для языка способы межпроцессного взаимодействия, и обращение, скажем, через сокет, ничуть не «интегрированнее», чем вызов инит-скрипта, а кода существенно требует больше.

annulen ★★★★★
()
Ответ на: комментарий от Kiborg

Моё имхо считает, что должен быть какой-то интерфейс типа библиотеки

Такой интерфейс был бы не плох для абстракции от инит-системы (там где нет service, дернуть что-то другое, на виндах, например), в случае прибивания гвоздями к systemd это теряет смысл (так как можно с тем же успехом дернуть systemctl restart)

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

annulen ★★★★★
()
Ответ на: комментарий от Kiborg

Я в «железке» это реализовывал средствами inotify следящего за определённой директорий.

imb ★★
()
Ответ на: комментарий от asaw

Документацию я уже нашел и пока изучаю. Кстати, вдруг кому пригодится: для upstart тоже есть DBus интерфейс.

Kiborg ★★★
() автор топика
Ответ на: комментарий от annulen

Возврат нуля гарантирует успешность завершения операции, куда надежнее.

Конечно, только речь идет об обработке ошибок. Причем, в С++, как в компилируемом языке, принято большинство ошибок выявлять ещё до начала работы программы, а не ошарашивать пользователя неожиданным сюрпризом по ходу дела, что используемая системная утилита не понимает входные параметры, потому что у неё внезапно поменялся интерфейс. Или её вообще удалили/забыли поставить.

В С++ вообще отсутствуют «нативные» для языка способы межпроцессного взаимодействия

С++ не нужны никакие «нативные для языка способы» потому что этот язык прекрасно расширяем библиотеками написанными на нем же. Вот их использование и есть самый правильный и надежный подход.

asaw ★★★★★
()
Ответ на: комментарий от annulen

По-моему как раз наоборот: если хочется, чтобы это работало независимо от системы, то самый простой путь — это system(service). А если прибивать гвоздями, то можно и DBus прикрутить.

Kiborg ★★★
() автор топика
Ответ на: комментарий от asaw

А DBus-интерфейс может внезапно поломать обратную совместимость, или вообще превратиться в какой-нибудь другой *bus. От поттерингошколоты всегда можно ожидать такую подлянку.

Вот их использование и есть самый правильный и надежный подход.

Ок. Тогда это должна быть библиотека для взаимодействия с инит-системами (см. другой комментарий), а не libdbus. И все равно остается потенциально ненадежная рантаймовая зависимость, которую невозможно перевести на этап компиляции.

annulen ★★★★★
()
Ответ на: комментарий от Kiborg

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

И продублировать то, что и так написано в systemctl (код не читал, но думаю там идет отправка dbus-сообщения, получение ответа, проверка результата и выход с соответствующим кодом). Возможно, с багами. Возможно, что этот код сломается с более новой или более старой версией systemd.

Да, сделав это рукаим ты избавляешься от создания проуесса, но я сомневаюсь, что в твоем случае это имеет хоть какое-либо значение.

annulen ★★★★★
()
Ответ на: комментарий от Kiborg

Может быть, в твоем случае и правда нужно использовать dbus-интерфейс, моя мысль была в том, что прежде чем заменять простой работающее решение на более сложное, нужно хорошо подумать, перевесит ли выигрыш от сложного решения усложнение твоего кода. Насколько я понимаю, в описанном случае выигрыш отсутствует в принципе.

annulen ★★★★★
()
Ответ на: комментарий от annulen

А DBus-интерфейс может внезапно поломать обратную совместимость, или вообще превратиться в какой-нибудь другой *bus. От поттерингошколоты всегда можно ожидать такую подлянку.

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

Ок. Тогда это должна быть библиотека для взаимодействия с инит-системами (см. другой комментарий), а не libdbus.

Считай dbus аналогом COM в винде. Там через COM дофига всего делается, включая DirectX. А тут прям нужно велосипед изобрести.

asaw ★★★★★
()
Ответ на: комментарий от annulen

В том-то и дело, что systemctl работает не так, я как раз специально проверил. У них для внутренних связей своя шина, которую (если я правильно понял) в будущем планируют заменить на kdbus, а обычный DBus предоставляет интерфейс, который не будет меняться (если только дополняться).

Так-то я могу и openssl дергать через system(), и это во многих случаях будет проще. Но все используют libssl и libcrypt почему-то, и я считаю, что это правильно.

Kiborg ★★★
() автор топика
Ответ на: комментарий от Kiborg

Так-то я могу и openssl дергать через system(), и это во многих случаях будет проще

Это немного разные вещи. Одно дело дернуть процесс раз в час и получить код вовзрата, другое дело постоянно гонять данные через пайп и полностью терять контроль над сетевым стэком. Хотя в busybox'е wget именно так https реализует.

annulen ★★★★★
()
Ответ на: комментарий от annulen

Ну еще есть ведь (обычно однократные) задачи создания сертификатов, не только «постоянно гонять данные через пайп». Понятно, что можно и так, и в каких-то случаях для кратковременных или тестовых поделок это оправданно, но грамотный подход — именно использование библиотеки.

В любом случае, всем спасибо, ответ на свои вопросы я получил.

Kiborg ★★★
() автор топика

не через D-Bus, а через какой-то свой сокет, либо через kdbus.

Вполне себе через dbus. Свой приватный сокет у него есть исключительно для тех случаев, когда dbus ещё не поднят, а kdbus ещё не смерджен (даже когда будет смерджен, будет слой совместимости, ну и в обёртках типа QtDbus наверняка сделают нативную поддержку).

Поэтому я посоветую dbus-интерфейс — как-никак, он был придуман ровно для этого.

intelfx ★★★★★
()
Ответ на: комментарий от Kiborg

К тому же, openssl предоставляет API, позволяющий создать SSL-соединение. Можно сказать его уровень абстракции соответсвует уровню решаемой задачи.

libdbus же не имеет никакого понятия о сервисах, она предоставляет интерфейс (сишный) для использования другого (текстового) интерфейса, и этот интерфейс зависит от инит-системы (например, sysvinit и openrc не предоставляют никакого dbus-интерфейса). Т.е. ты не переходишь к более высокому уровню абстракции, а меняешь шило на мыло.

Если бы была библиотека, позволяющая сделать что-то вроде

Service s("myservice");
bool ok = s.restart();

тогда был бы реально переход от низкоуровневого интерфейса (вызов процесса) к высокоуровневому (API библиотеки)

annulen ★★★★★
()
Ответ на: комментарий от intelfx

Ну я может что не так понял, но systemctl вызывает (через несколько уровней вложенности) в зависимости от того, какая шина, функцию bus_socket_write_message либо bus_kernel_write_message, и первая по сути своей send, а вторая работает через kdbus. Может я не так чего понял, но ни одного вызова из libdbus я не нашел.

Kiborg ★★★
() автор топика
Ответ на: комментарий от Kiborg

У них вместо libdbus собственная библиотека взаимодействия с [k]dbus.

(Когда смерджат kdbus, API стабилизируют и откроют.)

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от asaw

А Dbus запросто может и не быть установлен. Linux это не Windows и нельзя гарантировать, что что-то кроме ядра в нем есть.

peregrine ★★★★★
()
Ответ на: комментарий от asaw

Кстати, насколько я понял, планируется сам интерфейс dbus перетащить в systemd, который будет работать через kdbus. Так что оно будет везде.

asaw ★★★★★
()
Ответ на: комментарий от peregrine

Вот когда будет должна, тогда и буду думать как это сделать. ТС озвучивал другие требования. А в старых системах может запросто не быть и /sbin/service.

asaw ★★★★★
()
Ответ на: комментарий от peregrine

Программа, которая должна управлять systemd, должна работать на системах без dbus (который идет как зависимость у systemd)? Ну попробуй.

Если же речь не про systemd, а про все иниты сразу, то всё равно, похоже, придется обходиться без dbus — по крайней мере для openrc и sysv-init.

Kiborg ★★★
() автор топика
Ответ на: комментарий от Kiborg

У меня не сервис, а штука, которая должна переконфигурировать сеть и применить изменения, т. е. по сути сделать service network restart.

AFAIK нужно сигнал послать. man 7 signal, man 2 kill, man 2 signal

emulek
()
Ответ на: комментарий от emulek

В общем случае служба не обязана обрабатывать сигналы (хотя если обрабатывает, это, конечно, вариант). А init-у сигнал посылать бессмысленно: в сигнале ведь нельзя передать, с какой службой и что сделать.

Kiborg ★★★
() автор топика
Ответ на: комментарий от emulek

поддержу сигналы. А все кто переинициализацию сервиса предлагают через дбас делать, упоролись системдом.

Shadow ★★★★★
()
Ответ на: комментарий от Shadow

Я был бы не против, если бы любая служба обязана была обрабатывать какие-то сигналы, а что делать с остальными службами?

Kiborg ★★★
() автор топика
Ответ на: комментарий от Kiborg

В общем случае служба не обязана обрабатывать сигналы

автор «службы» может быть мудаком, да.

ну или эта «служба» просто в принципе не предназначена, для того, что-бы ей управляли.

ЗЫЖ какой-то windows way у вас тут. COM объекты… Тьфу на вас.

emulek
()
Ответ на: комментарий от Kiborg

Раньше httpd или squid чуть ли не кофе варили по сигналам. Раз модно не обрабатывать сигналы - в добрый путь. От Х ресурсов уже отказались, хотя отличный способ минимально привести тулкиты хотя бы к одному цвету ( можно было отказаться частично, но нет, надо радикально)

Shadow ★★★★★
()
Ответ на: комментарий от emulek

Ну попробуй, пошли сигнал службе, которая занимается монтированием дисков при загрузке, или любой другой службе, которая по своей сути не висит в процессах.

Kiborg ★★★
() автор топика
Ответ на: комментарий от Shadow

Я не вижу связи с топиком. Какая мне разница, что «раньше» умели httpd и squid? И повторю вопрос, который задал выше: что делать со службами, которые не должны висеть в памяти (в systemd Type=OneShot)?

Kiborg ★★★
() автор топика
Ответ на: комментарий от Kiborg

Ну попробуй, пошли сигнал службе, которая занимается монтированием дисков при загрузке, или любой другой службе, которая по своей сути не висит в процессах.

зачем? Какой в Этом смысл?

И портом, какой идиот написал эту фразу в этом топике: «У меня не сервис, а штука, которая должна переконфигурировать сеть и применить изменения, т. е. по сути сделать service network restart»?

emulek
()
Ответ на: комментарий от emulek

«Зачем» — в корне неверная постановка вопроса. На этот вопрос всегда есть ответ в духе «а почему бы и нет», «так надо», или, например «докажи, что это никому не может быть нужно». Какая вообще разница, зачем? У меня одна задача, у кого-то другая.

Дальше, я вообще-то ставил вопрос в общей форме, а про network пояснил для тех, кто не понял, что мне нужно сделать. Служба network — лишь одна из тех, которыми нужно управлять.

Что касается собственно network: это по сути скрипт, читающий конфигурацию и запускающий несколько других программ, в частности (при некоторых условиях) dhcpcd. Должен ли я, по-твоему, написать штуку, которая сначала изменяет конфиг, а потом делает абсолютно ту же работу, что и скрипт network (определяет, нужно ли прибить dhcpcd, и если нет, то какой сигнал ему послать и т. д.)? Или этот скрипт должен остаться висеть в памяти, ожидая, когда я пришлю ему сигнал?

идиот написал эту фразу в этом топике

Я не идиот, а остальные две копии этого сообщения в этом топике твои.

Kiborg ★★★
() автор топика
Ответ на: комментарий от Kiborg

докажи, что это никому не может быть нужно

это демагогия. Если это тебе действительно нужно, просто скажи: зачем? Мне иногда нужно, mount иногда виснет на VFS. Я её прерываю командой kill(1) посылая сигнал. ЧЯДНТ?

Служба network — лишь одна из тех, которыми нужно управлять.

ну ищи тогда API к своему systemd.

Должен ли я, по-твоему, написать штуку, которая сначала изменяет конфиг, а потом делает абсолютно ту же работу, что и скрипт network

лично я бы переписал скрипт network, зачем плодить лишние сущности?

Я не идиот

тогда ты должен понимать, что у разных задач должно быть разное решение. Ты спрашивал за network, я ответил. Сигналы — стандартное средство межпроцессорного взаимодействия в Linux.

Что до «общего случая», то пиши свой, принципиально новый systemd. Я разрешаю.

emulek
()
Ответ на: комментарий от emulek

То что мне нужно, я описал в ОП. Мне нужно рулить несколькими службами. Демагогия — выяснять, зачем мне это нужно. Это мое дело.

ну ищи тогда API к своему systemd.

Уже нашел.

лично я бы переписал скрипт network, зачем плодить лишние сущности?

Поясни, как именно переписал бы.

Kiborg ★★★
() автор топика
Ответ на: комментарий от Kiborg

Демагогия — выяснять, зачем мне это нужно. Это мое дело.

Поясни, как именно переписал бы.

тебе виднее, я не телепат.

emulek
()
Ответ на: комментарий от emulek

А раз сам не знаешь, зачем советуешь?

Kiborg ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.