Programm beenden erkennen - im Hintergrund

Rund um die LCL und andere Komponenten

Programm beenden erkennen - im Hintergrund

Beitragvon Timm Thaler » 6. Aug 2017, 00:46 Programm beenden erkennen - im Hintergrund

Ich habe ein Konsolenprogramm mit folgender Struktur im Hauptprogramm:

Code: Alles auswählen
begin
  InitProg()// <- hier Start in Logfile schreiben
  repeat
    MachWas();
    sleep(10);    // alle 10msec
    if KeyPressed then    //  Taste prüfen
      if ReadKey = ^C then     // wenn Ctrl-C
        Break;
  until false;
  CloseProg()// <- hier Ende in Logfile schreiben
end.         


Starte ich das Programm in der Konsole, kann ich es mit Ctrl-C beenden, und es schreibt brav Start und Ende ins Logfile.

Starte ich das Programm allerdings mit cron beim Start des Raspberry, habe ich ja keinen Zugriff per Ctrl-C. Ich kann das Programm entweder killen oder es wird gekillt, wenn ich den Raspi runterfahre. Beide Male wird das Ende aber natürlich nicht im Logfile vermerkt.

Gibt es eine Möglichkeit, das Programm im Hintergrund laufen zu lassen, es aber dennoch per Konsole ordentlich zu beenden bzw. bei Shutdown eine Beenden-Nachricht zu erhalten? Wie wird das bei Services gemacht, da gibt es auch start service und stop service?

Idealerweise soll das Programm
- über die Konsole beendet werden können
- beim Herunterfahren sauber beendet werden
- durch einen Cron Job täglich beendet und neu gestartet werden

Realisierbar? Mit vertretbarem Aufwand realisierbar?
Timm Thaler
 
Beiträge: 431
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Warf » 6. Aug 2017, 04:41 Re: Programm beenden erkennen - im Hintergrund

Du könntest eine Pipe verwenden z.B.
Code: Alles auswählen
program Project1;
 
{$mode objfpc}{$H+}
 
uses
  BaseUnix;
 
function StreamLength(Stream: cint): cint; inline;
begin
  FpIOCtl(Stream, 1074030207, @Result);
end;
 
var inStream: cint;
  c: Char;
begin
  if FpMkfifo(PChar('./test.pipe'), &0666) <> 0 then exit;
  try
    inStream := FpOpen(PChar('./test.pipe'), O_RDONLY);
    if inStream = 0 then exit;
    while True do
    begin
      if (StreamLength(inStream) > 0) And
      (FpRead(inStream, c, 1) = 1) And
      (c='q') then
        exit
    end;
 
  finally
    FpClose(inStream);
    FpUnlink(PChar('./test.pipe'));
  end;
end.
 
 


Dieses Programm läuft so lange bis q in die Pipe geschrieben wird. Zum beenden dann einfach
Code: Alles auswählen
echo q > test.pipe

verwenden.

Optimaler wäre es natürlich das Interrupt Signal SIGINT abzufangen. Ich bin mir nicht sicher aber ich glaube die TCustomApplication Klasse kann das behandeln.

Am besten wäre es einen Daemon zu schreiben, schön hier erklärt: http://wiki.freepascal.org/Daemons_and_Services. Wenn die Anwendung immer im Hintergrund laufen soll ist das genau was du suchst.
Warf
 
Beiträge: 616
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon braunbär » 6. Aug 2017, 10:20 Re: Programm beenden erkennen - im Hintergrund

Wenn ein Programm ordnungsgemäß herutergefahren wird, werden doch die finalization Abschnitte der verschiedenen Programmunits durchlaufen.
In so einen Abschnitt den Aufruf von Closeprog setzen, dann wird es ausgeführt, egal, wodurch die Programmbeendigung erfolgt.

Du musst nur darauf achten, dass die Units im uses in der richtigen Reihenfolge angegeben werden, dein closeprog muss aufgerufen werden, bevor die finalization von anderen Units, die dein closeprog braucht, schon erfolgt ist.

P.S. Ich habe mich noch nie mit Konsolenprgrammen beschäftigt, aber kann man nicht sogar direkt in der Hauptunit eines Konsolenprogramms einen initialization und einen finalization Abschnitt definieren?
braunbär
 
Beiträge: 164
Registriert: 8. Jun 2017, 17:21

Beitragvon Timm Thaler » 6. Aug 2017, 12:39 Re: Programm beenden erkennen - im Hintergrund

Das mit den Daemons gefällt mir. Ist wahrscheinlich die sauberste Lösung.

Unter http://wiki.freepascal.org/Daemons_and_Services steht:

Stop
Called when daemon should stop. This method must return immediately with True.
Shutdown
Called when daemon should be killed. This method must stop the daemon immediately and return with True. This is not triggered under Linux. Linux simply kills the daemon.


Wenn ich den Raspberry neu boote, wird dann Stop oder Shutdown ausgeführt? Bei Shutdown => kill hätte ich ja nix gewonnen, denn ein Logfile-Eintrag wird nicht erzeugt und eventuell gerade offene Dateien nicht geschlossen.
Timm Thaler
 
Beiträge: 431
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.6 FPC3.0.0, Raspbian Jessie Laz1.6 FPC3.0.0 | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Warf » 6. Aug 2017, 16:21 Re: Programm beenden erkennen - im Hintergrund

Timm Thaler hat geschrieben:Das mit den Daemons gefällt mir. Ist wahrscheinlich die sauberste Lösung.

Unter http://wiki.freepascal.org/Daemons_and_Services steht:

Stop
Called when daemon should stop. This method must return immediately with True.
Shutdown
Called when daemon should be killed. This method must stop the daemon immediately and return with True. This is not triggered under Linux. Linux simply kills the daemon.


Wenn ich den Raspberry neu boote, wird dann Stop oder Shutdown ausgeführt? Bei Shutdown => kill hätte ich ja nix gewonnen, denn ein Logfile-Eintrag wird nicht erzeugt und eventuell gerade offene Dateien nicht geschlossen.


Keine Ahnung, solltest du am besten einfach mal ausprobieren, würde mich auch interessieren.
Warf
 
Beiträge: 616
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

• Themenende •

Zurück zu Komponenten und Packages



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste

porpoises-institution
accuracy-worried