Lazarus. Daemon/Service

rgreat
Дата: 09.12.2019 21:52:21
Дайти плиз пример работающего сервиса на лазаре.

Пример на который ссылаются в вики (cleandirs.lpr) и что идет в комплекте не работает.

procedure CleanDirsDaemonCreate(Sender: TObject);
procedure CleanDirsDaemonStart(Sender: TCustomDaemon; var OK: Boolean);
procedure CleanDirsDaemonStop(Sender: TCustomDaemon; var OK: Boolean);

При запуске из винды эти события тупо не срабатывают, хотя в службах пишет что все ОК.
Док
Дата: 10.12.2019 00:11:02
rgreat,

тут (отсюда) и тут смотрел?
rgreat
Дата: 10.12.2019 01:56:39
Док
rgreat,

(отсюда) смотрел?
Это - нет.

Ситуация похожая.

Но у меня "В общем, непонятно как, но проблема решена." пока не выходит.
crutchmaster
Дата: 10.12.2019 03:56:48
rgreat,

google://NSSM
rgreat
Дата: 10.12.2019 04:43:28
crutchmaster,

С костылями я и сам могу. Мне бы корректное решение.
crutchmaster
Дата: 10.12.2019 04:58:58
rgreat
Мне бы корректное решение.

NSSM - это и есть корректное решение.
rgreat
С костылями я и сам могу.

Костыли - это эти все твои CleanDirsDaemonCreate, которые почему-то не срабатывают. Почему так происходит? Почему нельзя было сделать на sigterm, как у людей? Зачем им надо было кровь из носу изобретать велик?
Док
Дата: 10.12.2019 08:34:26
rgreat
Но у меня "В общем, непонятно как, но проблема решена." пока не выходит.

если посмотреть буржуйский форум, там тоже сервисы на винде не работают. Хотя, по самой первой ссылке в статье выложен тестовый проект. У меня он на XP и win7 заработал (сервис надо вручную запустить и остановить). При компиляции только нужно поправить пути для лог-файла, если нет диска D:\ (если есть, можно готовый экзешник из архива запустить)
MaratIsk
Дата: 10.12.2019 17:08:07
rgreat
Дайти плиз пример работающего сервиса на лазаре.

Пример на который ссылаются в вики (cleandirs.lpr) и что идет в комплекте не работает.

procedure CleanDirsDaemonCreate(Sender: TObject);
procedure CleanDirsDaemonStart(Sender: TCustomDaemon; var OK: Boolean);
procedure CleanDirsDaemonStop(Sender: TCustomDaemon; var OK: Boolean);

При запуске из винды эти события тупо не срабатывают, хотя в службах пишет что все ОК.
rgreat
Дата: 10.12.2019 21:34:17
Док
rgreat
Но у меня "В общем, непонятно как, но проблема решена." пока не выходит.

если посмотреть буржуйский форум, там тоже сервисы на винде не работают. Хотя, по самой первой ссылке в статье выложен тестовый проект. У меня он на XP и win7 заработал (сервис надо вручную запустить и остановить). При компиляции только нужно поправить пути для лог-файла, если нет диска D:\ (если есть, можно готовый экзешник из архива запустить)
Скомпилил, ничего не меняя.
Сервис инсталлится, запускается, но D:\log.txt не появляется.

http://rgreat.ru/tmp/Delphi/Devlaz.exe


MaratIsk
Красивый подход, жаль что также не работает.
Пришлось допилить чтоб компилировалось + добавил свой логгер.

Лог при старте из сервисов:
10.12.2019 21:29:49.423: Clearing Logs...
10.12.2019 21:29:49.424: RunApplication. StartService = -1, Installing = 0
10.12.2019 21:31:06.098: RunApplication End.

Проект и exe:
http://rgreat.ru/tmp/Delphi/Daemon.zip
rgreat
Дата: 10.12.2019 21:58:33
crutchmaster
Костыли - это эти все твои CleanDirsDaemonCreate, которые почему-то не срабатывают. Почему так происходит? Почему нельзя было сделать на sigterm, как у людей? Зачем им надо было кровь из носу изобретать велик?

Это вопрос к разработчикам PFC/Lazarus.

Мопед не мой, я только разместил объяву.

Я только хотел иметь работающий "стандартно" кроссплатформенный код.

На дельфях я вон намонстрячил в подобном виде:

+ Posix.Daemon.pas
unit Posix.Daemon;

// http://blog.paolorossi.net/2017/09/04/building-a-real-linux-daemon-with-delphi-part-2/

// The standard location of syslog log is /var/log/syslog
// tail -f /var/log/syslog

interface

uses
  System.SysUtils,
  System.IOUtils,
  Posix.Stdlib,
  Posix.SysStat,
  Posix.SysTypes,
  Posix.Unistd,
  Posix.Signal,
  Posix.Fcntl,
  Log;

procedure InitDaemon;

var
  pid, sid: pid_t;
  fid: Integer;
  Running: Boolean;

const
  // Missing from linux/StdlibTypes.inc !!! <stdlib.h>
  EXIT_FAILURE = 1;
  EXIT_SUCCESS = 0;

implementation

// 1. If SIGTERM is received, shut down the daemon and exit cleanly.
// 2. If SIGHUP is received, reload the configuration files, if this applies.
procedure HandleSignals(SigNum: Integer); cdecl;
begin
  case SigNum of
    SIGTERM:
    begin
      Running := False;
    end;
    SIGHUP:
    begin
      StrToLog('daemon: reloading config');
      // Reload configuration
    end;
  end;
end;


procedure InitDaemon;
var
  idx: Integer;
const
  Debug = False;
  WriteStdOut = False;
  Sequrity = False;
  ChangeDir = False;
begin
  // If the parent process is the init process then the current process is already a daemon
  // Remarks: this check here
	if getppid() = 1 then
  begin
    if Debug then StrToLog('Nothing to do, I''m already a daemon');
    Exit; // already a daemon
  end;

  if Debug then StrToLog('before 1st fork() - original process');

  // Call fork(), to create a background process.
  pid := fork();

  if Debug then StrToLog('after 1st fork() - the child is born');

  if pid < 0 then
    raise Exception.Create('Error forking the process');

  // Call exit() in the first child, so that only the second
  // child (the actual daemon process) stays around
  if pid > 0 then
    Halt(EXIT_SUCCESS);

  if Debug then StrToLog('the parent is killed!');

  // This call will place the server in a new process group and session and
  // detaches its controlling terminal
  sid := setsid();
  if sid < 0 then
    raise Exception.Create('Impossible to create an independent session');

  if Debug then StrToLog('session created and process group ID set');

  // Catch, ignore and handle signals
  signal(SIGCHLD, TSignalHandler(SIG_IGN));
  signal(SIGHUP, HandleSignals);
  signal(SIGTERM, HandleSignals);

  if Debug then StrToLog('before 2nd fork() - child process');

  // Call fork() again, to be sure daemon can never re-acquire the terminal
  pid := fork();

  if Debug then StrToLog('after 2nd fork() - the grandchild is born');

  if pid < 0 then
    raise Exception.Create('Error forking the process');

  // Call exit() in the first child, so that only the second child
  // (the actual daemon process) stays around. This ensures that the daemon
  // process is re-parented to init/PID 1, as all daemons should be.
  if pid > 0 then
    Halt(EXIT_SUCCESS);
  if Debug then StrToLog('the 1st child is killed!');
  StrToLog('Daemon creation is done.');

  // Open descriptors are inherited to child process, this may cause the use
  // of resources unneccessarily. Unneccesarry descriptors should be closed
  // before fork() system call (so that they are not inherited) or close
  // all open descriptors as soon as the child process starts running

  idx:=0;
  if idx<>0 then;
  
  if not WriteStdOut then begin
    // Close all opened file descriptors (stdin, stdout and stderr)
    for idx := sysconf(_SC_OPEN_MAX) downto 0 do
      __close(idx);

    if Debug then StrToLog('file descriptors closed');

    // Route I/O connections to > dev/null

    // Open STDIN
    fid := __open('/dev/null', O_RDWR);
    // Dup STDOUT
    dup(fid);
    // Dup STDERR
    dup(fid);

    if Debug then StrToLog('stdin, stdout, stderr redirected to /dev/null');
  end;

  if Sequrity then begin
    // Set new file permissions:
    // most servers runs as super-user, for security reasons they should
    // protect files that they create, with unmask the mode passes to open(), mkdir()
    // Restrict file creation mode to 750
  	umask(027);
    if Debug then StrToLog('file permission changed to 750');
  end;

  if ChangeDir then begin
    // The current working directory should be changed to the root directory (/), in
    // order to avoid that the daemon involuntarily blocks mount points from being unmounted
    chdir('/');
    if Debug then StrToLog('changed directory to "/"');
  end;
end;

end.

uses
  {$IFDEF POSIX}
  Posix.Daemon,
  {$ENDIF }

begin
{$IF Defined(POSIX) and Defined(RELEASE)}
  InitDaemon;
{$ENDIF}

Я вот вот все никак не могу выбрать себе грабли.

1. Дельфя - это огромный плюс к совместимости со старым кодом и вообще инструмент гораздо более удобный в разработке.
Но там пока огромные грабли с графикой под линукс. FMX для графики полное говно, а работающих альтернатив - просто нет.
А графика нужна.
Вот сейчас аж BGRABitmap library пытаюсь прикрутить. Пока не выходит.

2. Лазарь имеет хорошую кроссплатформенность и удовлетворительную поддержку графики даже в headless linux.
Но он гораздо менее удобен в разработке. Имеет не юникодный RTL и хронический недостаток документации и примеров.
Часть функционала может внезапно глючить или не работать как задумано.
Ну и кол-во переделок сущестующего кода удручает.