LINUX.ORG.RU

Запуск программы как демона

 


0

2

Такая ситуация: приложение использует старую библиотеку (только .so файлы), которые поправить нет возможности. При обычном запуске под рутом через терминал из любой директории или через менеджер файлов, программа запускается и работает нормально. Но стоит указать ее как демона где то в глубине этой библиотеки возникает ошибка:

terminate called after throwing an instance of ‘std::logic_error’ what(): basic_string::_S_construct null not valid

Очевидно что где то там внутри нее передается NULL как аргумент в string и который не NULL если запускается как обычное приложение. Не знаю что это за параметр, но по идее разницы же быть не должно запускается программа через systemd или менеджер файлов? Или все таки есть? Откуда она об этом может знать?

Вам нужно проверить, что при запуске от обычного пользователя так же всё работает при ручном запуске.

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

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

Если так уж нужно от root - пропишите в параметрах systemd unit файла, что запуск идёт от root.

kostik87 ★★★★★
()

Можешь запустить ее в обычном режиме при помощи: tmux, sctreen, supervisord, immortal и кучи других тулзеней. Чтоб стартовало при запуске системы – накидай небольшой скриптик, который стартанет ее через тулзу.

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

Что в твоём понимании демон? Демоны есть в аду и в FreeBSD.

В современных Linux дистрибутивах есть сервисы.

Которые в зависимости от системы инициализации запускаются:

  • через init скрипты ;
  • systemd unit файлы .

И можно добавлять Init скрипт на уровень запуска или активировать и деактивировать unit файл.

В параметрах init скрипта или unit файла указывается режим запуска процесса приложения и пользователь от которого запускается.

И задается команда запуска.

Далее если сервис включен система инициализации выполняет команду запуска, запускает программу в фоне и перенаправляет её поток вывода в журнал.

Отличия запуска некоторой программы в командной (SHELL) оболочке от запуска через сервис только в том, что сервисом удобнее управлять и можно легко добавить на запуск через систему инициализации при запуске системы и собрать логи.

А относительно приложения - есть режим запуска в background - это как раз таки демон, например nginx с соответствующим ключом или sshd с соответствующим ключом или запуск в режиме, когда приложению нужна активная сессия оболочки.

В первом сообщении в теме я написал что предлагаю:

Вам нужно проверить, что при запуске от обычного пользователя так же всё работает при ручном запуске.

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

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

У вас проблема с пониманием материала или терминологией?

Мне писать более короткие предложения?

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

я все понял, хорошо пусть сервис, я работаю и запускаю сейчас все только под рутом, без всяких су и судо. В системе (ЦентОС8)используется systemd. От типа сервиса не зависит пытался и простой и форкнутый, от аргументов в командной строке не зависит.

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

Ты предлагаешь на демона вообще забить

Да. А чем по сути foregroud режим отличается от background? По большей мере это: выполнение fork() и продолжение работать в потомке, логирование (если предусмотрено) в отдельный файл вместо stdout и сброс привилегий рута до обычного смертного, что может делать и в foregroud режиме.

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

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

И что из этого, смысл в написанном выше был в другом.

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

Если посмотреть man sshd - он по умолчанию запускается в background, а если задать ключ -D - в режиме foreground и осуществляет вывод в консоль, где его запустили.

-D      When this option is specified, sshd will not detach and does not become a daemon.  This allows easy monitoring of sshd

Если не понимаешь в чём суть разговора - не пиши.

Вот я как раз и пишу:

А относительно приложения - есть режим запуска в background - это как раз таки демон, например nginx с соответствующим ключом или sshd с соответствующим ключом или запуск в режиме, когда приложению нужна активная сессия оболочки.

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

да сделал, явно указал рута, результат без изменений, система виснет при загрузке одного из внутренних so-файла библиотеки, в системном лог - та же ошибка о передаче NULL параметра в string

Hunter1972
() автор топика

Очевидно что где то там внутри нее передается NULL как аргумент в string и который не NULL если запускается как обычное приложение. Не знаю что это за параметр, но по идее разницы же быть не должно запускается программа через systemd или менеджер файлов?

например если запускать через сустемд, то программе по дефолту будет передан /dev/null в качестве stdin. Попробуй запустить ее с strace и посмотреть, что там за сисколлы перед этой ошибкой. Или отладчиком подключись, символы там похоже есть.

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

Покажи systemd unit, что написал.

Покажи пример запуска твоей программы в командной строке, где всё работает.

Покажи логи сервиса systemd (unit`а) с сообщениями от программы.

Режими запуска процесса через systemd unit пробовал менять?

https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html

Читай про параметр type и пробуй.

После редактирования unit файла нужно делать systemctl daemon-reload.

Плюс, возможно, в переменных окружения SHELL, например в PATH или LD_PRELOAD / LIBRARY_PATH у тебя указано подгружать библиотеки по некоторому пути.

В Systemd Unit свои переменные, если они нужны - задай их.

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

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

Если не понимаешь в чём суть разговора - не пиши.

То есть ты только сейчас узнал что такое демон, и имеешь наглость указывать кому что писать? А суть разговора мне не интересна, я просто ткнул тебя в ложное заявление.

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

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

Повторю ещё раз термин демон был в первую очередь противопоставлен терминам сервис и systemd unit в системе инициализации Linux. Против демонов в FreeBSD.

В FreeBSD демоны - это служба. И одновременно же демон - способ запуска приложения в фоне.

Режим запуска программы в режиме демона - это другое.

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

По крайней мере это моя вольная интерпретация его сообщения.

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

Если тебе ещё что не понятно в моих выводах и допущениях при написании сообщений в данной теме пиши - разжую, обращайся.

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

В общем сделал основные тесты

  1. при запуске с терминала (рут) без fork: fg, bg - отлично c fork, работа в потомке, ppid=1 - тоже отлично
  2. в качестве сервиса systemd и без fork (simple) и с fork (forking) - не работает ни в каком виде, при загрузке одной из их внутренних so-шек, ошибка NULL, я по очереди их динамически подгружал чтобы выявить виноватую, другие so-шки, все подгружаются нормально, так что с путями по идее все должно быть в порядке.
  3. программа не использует ни ввод ни вывод в консоль, всё закрыто
  4. selinux (редхетовская безопасность) отключен

То есть на текущий момент рабочий вариант от айрона, забить на системд и не париться

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

Понимаете, способ точно есть. Вы вот это прочитали?

Плюс, возможно, в переменных окружения SHELL, например в PATH или LD_PRELOAD / LIBRARY_PATH у тебя указано подгружать библиотеки по некоторому пути.

tmux, sctreen, supervisord, immortal и кучи других тулзеней

@iron написал вот это и вы про и говорите..

Смысл в том, что при таком запуске у вас подтягиваются те же переменные окружения и прочие настройки SHELL, в которых вы сейчас запускаете.

А при запуске через systemd unit даже переменная PATH будет другая, то, что прописано в ~/.bashrc и прочих конфигах так же не подтянется, поэтому у вас и не работает.

Вы как-то частично слушаете рекомендации и частично их выполняете.

Понимаю, что вам хватает опыта и знаний.

Вы можете, например, написать простой bash скрипт и в нём сделать вывод в файл переменных окружения и настроек и запустить его в systemd, увидите с каким окружением запускается там и с каким запускаете вы в SHELL вручную и просто сравните.

Создаёте директорию /tmp/systemd и /tmp/shell

Скрипт прост:

#!/bin/bash
set > /tmp/systemd/set.out
export > /tmp/systemd/export.out

Можно ещё добавить вот это

ldd /путь/до/вашей/программы/program > /tmp/systemd/ldd.out

Вместо bash можете указать ваш SHELL - это может быть важно.

Всё, выполняете эти же команды, только с выводом в другие файлы.

В вашем SHELL:

set > /tmp/shell/set.out
export > /tmp/shell/export.out
ldd /путь/до/вашей/программы/program > /tmp/shell/ldd.out

Сравниваете, можно через diff.

diff -ur /tmp/shell /tmp/systemd

Всё, находите разницу в настройке окружения - выставляете так же в systemd unit файле, запускаете, радуетесь.

Можете написать скрипт запуска программы и запускать его, но настройки окружения лучше проверить.

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

Вот у вас так же.

В начале - как запустить как демон.

Вам написал как и что нужно проверить, но вам сложно и вы уже вроде как готовы сделать не так, как хотели изначально.

Мне всё равно, просто интересно это наблюдать.

Как только человек понимает, что он не понимает. Он считает, не что он не прав и невозможно, собственно из-за него (человека), потому, что ему не хватает знаний, а говорит, что невозможно в принципе и будут делать хоть как-то.

Честно, вот просто весело )))

Для systemd точно должны быть какие-то анализаторы запуска, но так, как я привёл 100% будет достаточно для анализа.

Удачи, запускайте так, как вам удобнее.

Я не обещал вам готовое решение я лишь показал и пояснил как это работает и какими способами можно провести анализ и достичь результата.

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

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

Спасибо! Все протестю, конечно хотел бы готовый(почти) ответ получить, но готовый алгоритм поиска это тоже шикарно. Вообще со временем так туго стало, что недавно меня просто выбесила игра в шахматы, дочка попросила сыграть, а я чуть доску не выкинул. Показалось кощунственным тратить мозговую активность на эту хрень, читать фантастику или тупо играть это пожалуйста, а вот думать - ни ни.

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

Такая ситуация: приложение использует старую библиотеку (только .so файлы), которые поправить нет возможности.

Гм. А версия с ошибкой в софте не рассматривается? Может эта поделка в принципе никогда не умела работать как демон.

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

Я бы попробовал запустить эту поделку через ltrace и посмотрел бы на чём она падает.

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

То что там ошибка, это без вариантов, хотя бы проверку на NULL могли вставить, но она неисправима поскольку фирма мертва, поэтому хочу просто обойти ее, работать она точно умела, но да, не факт что в демоне. Виснет на dlopen одного из внутренних файлов. Как здесь и советовали буду сравнивать и заменять переменные окружения и смотреть когда заработает, по идее должна. Про системд она, почти уверен, не знала никогда. А ltrace что может дать то? То что при загрузке .so файла я и так знаю.

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

В ltrace видны вызовы libc. Если функция работает со строками, то они видны. Это иногда очень помогает понять, что оно ищет в переменных окружения или в файлах.

Ещё можно попробовать запустить через strace. Там видны системные вызовы.

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

Через что запускается прикладная программа (через systemd или sysvinit) самой программе знать нет необходимости.

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

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

Hunter1972
() автор топика
Ответ на: комментарий от vel
  1. В первом приближении указание переменных окружения для системд не прокатило, но пока я указал не все а только те которые имеют хоть какое то отношение на мой взгляд
  2. с ltrace такая ситуация, сравнил нормальный запуск и от системд, нашел момент когда пошли различия (первые 5 строк идентичные):

нормальный запуск (pid 35889):

[pid 35892] set_robust_list@SYS(0x7f2cf49209e0, 24, -160, 0x7f2cf49209d0 <unfinished …>
[pid 35889] prlimit64@SYS(0, 7, 0, 0x7ffc076b40e0 <unfinished …>
[pid 35892] <… set_robust_list resumed> ) = 0
[pid 35889] <… prlimit64 resumed> ) = 0
[pid 35892] mmap@SYS(nil, 134217728, 0, 16418, -1, 0 <unfinished …>
[pid 35889] openat@SYS(AT_FDCWD, «inter.cfg», 0, 00 <unfinished …>

запуск от системд (pid 34312):

[pid 34315] set_robust_list@SYS(0x7fe378f5a9e0, 24, -160, 0x7fe378f5a9d0 <unfinished …>
[pid 34312] prlimit64@SYS(0, 7, 0, 0x7ffe5ed43970 <unfinished …>
[pid 34315] <… set_robust_list resumed> ) = 0
[pid 34312] <… prlimit64 resumed> ) = 0
[pid 34315] mmap@SYS(nil, 134217728, 0, 16418, -1, 0 <unfinished …>
[pid 34312] futex@SYS(0x7fe389c55040, 129, 0x7fffffff, 0 <unfinished …>
[pid 34315] <… mmap resumed> ) = 0x7fe37075a000
[pid 34312] <… futex resumed> ) = 0
[pid 34315] munmap@SYS(0x7fe37075a000, 59400192 <unfinished …>
[pid 34312] write@SYS(2, «terminate called after throwing an instance of ’», 48 <unfinished …>
[pid 34315] <… munmap resumed> ) = 0 terminate called after throwing an instance of ’[pid 34312] <… write resumed> ) = 48
[pid 34315] munmap@SYS(0x7fe378000000, 7708672 <unfinished …>
[pid 34312] write@SYS(2, «std::logic_error», 16 <unfinished …>
[pid 34315] <… munmap resumed> ) = 0 std::logic_error
[pid 34312] <… write resumed> ) = 16

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

Ну если совсем всё туго - можешь попробовать запускать через screen, но в systemd unit файле.

Сможешь запускать как сервис и останавливать.

screen vm
screen htop

Вот запуск в screen редактора vim или утилиты htop.

Для screen нужны дополнительные ключи, чтобы сам screen сразу в detach режиме запускался.

Погугли, не помню сейчас.

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

Всё, разобрался, в последних тестах оказался чисто мой косяк. При тщательной проверке переменных окружения в конфиге сервиса, где везде добавляешь Environment=, оказалось что пропала первая буква одной переменной. Естественно именно в ней дело и оказалось. Сейчас программа под системд работает также как и через терминал. Там есть и другие косяки но с системд уже не связаны, а то мистика какаято была.

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

Ну вот видишь, немалая часть проблем в работе чего-либо находится между монитором и стулом. Т.е. виновата, как правило прослойка между клавиатурой и табуреткой.

Некоторые её называют человек, пользователь, юзверь, программист, администратор, в зависимости от качества этой прослойки.

Ты молодец, что разобрался всё же и нашёл свой косяк.

kostik87 ★★★★★
()