Forum > Beginners

[Linux] Program that runs in the background

<< < (2/3) > >>

Warfley:
I generally advise against using a LazDaemon application on Linux, because it is designed around the Windows API structure for services, which is rather complicated. Like this whole putting your functionatlity in a worker thread that is then signalised through some event methods comes from the way the Windows handles Services.
When you are not targeting Windows, this is all overhead that you do not need, because Daemons on Linux are really easy, because they are just console applications (in fact on Linux every application is a console application, the idea that there are different types of applications is a Windows only concepts).

So to create a daemon for linux is really easy:
Step 1: Create and debug your application as console application
Step 2: Run it in the background

To run an application in the background a few things where already mentioned. Here is some further information.
To run an application from your shell in the background, you need to add an & after the command:

--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---$> ./myapplication &There you have two Problems, the first one is that your console output is still bound to the terminal you started your program in, so if you close it and your program tries to do a WriteLn, it will get a broken pipe error, and this probably crashes your application. So you need to handle the output.
If you want to log the output, you can just write it into a file:

--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---$> ./myapplication > logfile.txt 2>&1 &The 2>&1 pipes the stderr over the same output as stdout, if you want different logs:

--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---$> ./myapplication > output.log 2> error.log &If you want to have it a bit nicer with timestamps, you can also add them through bash:

--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---$> ./myapplication 2>&1 | ts > log.txt &but this limits a bit your abilities (e.g. creating a seperate log for stderr, or taking the PID, which I will come to later), so maybe its better to timestamp within your application, e.g. by using a logging library
You can also completely ignore the output by piping it to /dev/null

--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---$> ./myapplication > /dev/null 2>&1 &
The next problem is that when the shell that opend your program closes, your progrem gets the HUP signal sent, the default action is to close the program. There are two options to avoid this, either start your program via nohup, which basically just catches this signal and ignores it, and everything else is just passed through to your application:

--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---$> nohup ./myapplication > log.txt 2>&1 &
This is very basic to start a program in the background from your shell. You might want to find that program again later, in which case you might want to save the pid:

--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---$> ./myapplication > /dev/null 2>&1 &$> PID=$!which you can then store locally, e.g. to kill the process later:

--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---$> ./myapplication > /dev/null 2>&1 &$> PID=$!$> echo $PID > myapp.pid# Killing the process later$> PID=$(<myapp.pid)$> kill $PIDSo you could just create two simple bash scripts, runService.sh:

--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---#!/bin/bashset -enohup ./myapplication > output.log 2> error.log &echo $! > myapplication.pidand stopService.sh:

--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---#!/bin/bashset -ePID=$(<myapplication.pid)kill $PIDand voiala you can use these scripts for any console application to turn it into a servcie.
And I think it should be very obvious why I think that these two twoliner bash scripts are much more easy to use than to create a Deamon application as described in the wiki. So for Linux I see absolutely no reason to use the LazDaemon package.

If you want them a bit nicer you can also add some error checking:

--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---#!/bin/bashset -eif [ -f myapplication.pid ]; then  echo Service already started... please stop first or delete myapplication.pid if the service is not running  exitfinohup ./myapplication > output.log 2> error.log &echo $! > myapplication.pidand stopService.sh:

--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---#!/bin/bashset -eif [ ! -f myapplication.pid ]; then  echo Service is not running  exitfiPID=$(<myapplication.pid)kill $PID
Lastly, an alternative that I personally find better than this, is to simply execute the app on a virtual terminal. This is possible via screen or tmux.
You can just open a screen or tmux session, start your console application in there, and then detach from it. In tmux you simply enter the command tmux, then you get a new shell where you call your program (normally, non of this nohub or logging stuff from above) and then you press ctrl followed by ctrl + d to detach.
Your program now runs in a tmux session. When you want to revisit it, simply type "tmux attach" and you are back in the session. There you can see at all the output your program has generated, and you can even provide input (i.e. use readline and co). And later simply detach again to let it run in the background.

Thats in my opinion the best way to run applications in the background, if they do not have to be started automatically boot. If this is the case, you should simply use the scripts shown earlier and put them into an init script, systemd configuration, cronjob, xinit script or whatever you want to use to run a program on boot

abdoun.brahim:
Hello
Thank you very much
I found this code I tested:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program TimeLogger;{$APPTYPE CONSOLE}{$mode objfpc}{$H+} uses{$IFDEF UNIX}{$IFDEF UseCThreads}cthreads,{$ENDIF}{$ENDIF}Classes  , sysutils ,baseunix{ you can add units after this }; varTextF: TextFile;begintry  if fpfork()<>0 then begin     exit;  end;repeatAssignFile(TextF, 'log.txt');if FileExists('log.txt') thenAppend(TextF)elseRewrite(TextF); Writeln(TextF, DateTimeToStr(Now)); CloseFile(TextF);Sleep(10000); until false;except   on e:exception do   Writeln(TextF, DateTimeToStr(Now)+': erreur:'+e.message);end;end. 

dbannon:
yes Abdoun, that will work but if you read the responses you see here, you would realise that most of it is unnecessary. And unnecessary code is bad code.

Without testing -

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program TimeLogger;{$APPTYPE CONSOLE}{$mode objfpc}{$H+} uses{$IFDEF UNIX}{$IFDEF UseCThreads}cthreads,{$ENDIF}{$ENDIF}Classes  , sysutils ,baseunix{ you can add units after this }; begin    repeat        Writeln(DateTimeToStr(Now));        Sleep(10000);    until false;end.
Start it with nohup command and you will find your datestamp lines in the file 'nohup' or read Warfley's means of directing it to a specific file.

D


Warfley:
It's not just that this is uneccessary code, it also makes debugging of this application impossible. You are just going to make your life harder with this.

Just create a normal command line application that is easy to create and debug, and then execute it in the background as described above

MarkMLl:

--- Quote from: Warfley on May 13, 2022, 09:32:26 am ---It's not just that this is uneccessary code, it also makes debugging of this application impossible. You are just going to make your life harder with this.

Just create a normal command line application that is easy to create and debug, and then execute it in the background as described above

--- End quote ---

I strongly agree, but it's worth noting that the fork() technique is a transcription of legacy C code from some unspecified source (I hope it wasn't the FPC wiki).

The result is, by absolutely any standards, an unacceptable hodgepodge: on the one hand it uses traditional C/unix "lean and mean" fork(), on the other it introduces exception handling and a textfile which are very much "non-C".

MarkMLl

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version