Building a (real) Linux daemon with Delphi
Paolo Rossi - July 11, 2017
Paolo Rossi - July 11, 2017
[SHOWTOGROUPS=4,20]
Building a (real) Linux daemon with Delphi Series
So let's start!
Introduction
In the past weeks I've been busy converting some REST services, built with the Для просмотра ссылки Войдиили Зарегистрируйся, to Linux. Compiling the projects to Linux was the easy part, thanks to the great job Embarcadero did on the Linux compiler and the RTL.
For debugging and testing purposes, a console Linux application was sufficient but to deploy the service (actually on a AWS Linux instance) a simple console was not an option, so I've decided to build a Linux Daemon for that purpose.
Problem is that Delphi (at least in 10.2 Tokyo) doesn't support the creation of a Linux Daemon with an application template, so you have to build one for yourself using directly Linux system calls.
Для просмотра ссылки Войдиили ЗарегистрируйсяДля просмотра ссылки Войди или Зарегистрируйся
My setup: tools & applications
In order to be able to run, control and run application under Linux you must obviously have some (additional) software installed in your machine, my setup:
There are already some articles that explain in detail the process, and I'm actually writing an article on installing Debian 9 from scratch and configuring it for Delphi development, so.. stay tuned.
Launching a process in Linux
First of all if you have the Linux machine already configured for Delphi development, you can create a simple console application in Delphi, this one would be fine for our "launching program" exercise:
Now if you want to be able to launch your program under Linux independently (not via Delphi IDE) you must deploy your application (the "Deploy DemoConsole" menu command in the Delphi IDE). Now you have to launch your application in Linux, how to do it?
Remember that you have already opened several programs by typing ls, apt-get, wget, etc... so, to launch a Linux command (program) you simply have to write the command name in the shell, so let's try with our newly created Delphi program DemoConsole:
paolor@debian-9:˜$ DemoConsole
and...... doesn't work! :-(
Introducing the ./ (dot-slash)
The previous command failed because in Linux (Unix) the current directory is not in the current path (for security reasons) so you have to specify yourself the path:
where ./ is the current directory
Great, now you program is (finally) running, but you notice that you can't use that console (for other commands and so on) until your process is terminated.
And yes, of course you can always use another console to log into the system
but this is far less than ideal. This is what happens when you start the process with ./DemoConsole:
The & option (starting a background job)
Another option is to launch your process appending a & after the process name:
so the console will be immediately available to you! Great! it seems to be the perfect way to launch your service but.. it's not! So here what happens:
nohup and disown on the rescue
So even with & the background process in not detached from the console, to do so we have 2 options: the commands disown and nohup. Basically they do the same thing, they detach the process from the shell isolating it from SIGHUP signals, but they are slightly different though:
to use nohup:
to use disown:
or if you forget to put your program in background:
other differences:
Для просмотра ссылки Войдиили ЗарегистрируйсяДля просмотра ссылки Войди или Зарегистрируйся
Conclusions
In this article we explored the options for launching our (standard) console application (that must behave as a service) in Linux and the preferred way seems to be the nohup command. This solution works but a real Linux daemon is by far the better way to deploy "services" on the Linux platform and even more so is the "official" way in UNIX OSes but to be able to build a daemon in Delphi you have to wait the next article, stay tuned!
[/SHOWTOGROUPS]
Building a (real) Linux daemon with Delphi Series
- Part 1: Process management in Linux
- Part 2: Build a Linux daemon with Delphi
So let's start!
Introduction
In the past weeks I've been busy converting some REST services, built with the Для просмотра ссылки Войди
For debugging and testing purposes, a console Linux application was sufficient but to deploy the service (actually on a AWS Linux instance) a simple console was not an option, so I've decided to build a Linux Daemon for that purpose.
Problem is that Delphi (at least in 10.2 Tokyo) doesn't support the creation of a Linux Daemon with an application template, so you have to build one for yourself using directly Linux system calls.
Для просмотра ссылки Войди
My setup: tools & applications
In order to be able to run, control and run application under Linux you must obviously have some (additional) software installed in your machine, my setup:
- Windows 10 as host OS
- VirtualBox as virtualization software (Для просмотра ссылки Войди
или Зарегистрируйся) - Debian 9 Stretch as Linux OS (Для просмотра ссылки Войди
или Зарегистрируйся) or Ubuntu Server 16.04.2 LTS (Для просмотра ссылки Войдиили Зарегистрируйся) - Putty as terminal emulator (Для просмотра ссылки Войди
или Зарегистрируйся) or the Ubuntu Bash Shell if you have Windows 10 Anniversary Edition (Для просмотра ссылки Войдиили Зарегистрируйся) - WinSCP as SCP client for Windows (Для просмотра ссылки Войди
или Зарегистрируйся) or the Ubuntu Bash Shell if you have Windows 10 Anniversary Edition (Для просмотра ссылки Войдиили Зарегистрируйся) - Delphi 10.2 Tokyo to create applications for Linux, what else? (Для просмотра ссылки Войди
или Зарегистрируйся)
There are already some articles that explain in detail the process, and I'm actually writing an article on installing Debian 9 from scratch and configuring it for Delphi development, so.. stay tuned.
Launching a process in Linux
First of all if you have the Linux machine already configured for Delphi development, you can create a simple console application in Delphi, this one would be fine for our "launching program" exercise:
Код:
program DemoConsole;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
begin
try
Writeln('Hello World');
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Now if you want to be able to launch your program under Linux independently (not via Delphi IDE) you must deploy your application (the "Deploy DemoConsole" menu command in the Delphi IDE). Now you have to launch your application in Linux, how to do it?
Remember that you have already opened several programs by typing ls, apt-get, wget, etc... so, to launch a Linux command (program) you simply have to write the command name in the shell, so let's try with our newly created Delphi program DemoConsole:
paolor@debian-9:˜$ DemoConsole
and...... doesn't work! :-(
Introducing the ./ (dot-slash)
The previous command failed because in Linux (Unix) the current directory is not in the current path (for security reasons) so you have to specify yourself the path:
Код:
paolor@debian-9:˜$ ./DemoConsole
where ./ is the current directory
Great, now you program is (finally) running, but you notice that you can't use that console (for other commands and so on) until your process is terminated.
And yes, of course you can always use another console to log into the system
but this is far less than ideal. This is what happens when you start the process with ./DemoConsole:
- The process DemoConsole is created
- The process inherits stdin, stdout, and stderr from the shell
- The process receives SIGHUP signals (possibly) sent to the shell
- The shell is blocked until the process terminates
The & option (starting a background job)
Another option is to launch your process appending a & after the process name:
Код:
paolor@debian-9:˜$ ./DemoConsole &
so the console will be immediately available to you! Great! it seems to be the perfect way to launch your service but.. it's not! So here what happens:
- The process DemoConsole is created.
- The process inherits stdout/stderr from the shell (not the stdin)
- As soon as the process tries to read from stdin, the process halts!
- The process receives SIGHUP signals sent to the shell.
nohup and disown on the rescue
So even with & the background process in not detached from the console, to do so we have 2 options: the commands disown and nohup. Basically they do the same thing, they detach the process from the shell isolating it from SIGHUP signals, but they are slightly different though:
to use nohup:
Код:
paolor@debian-9:˜$ nohup ./ConsoleDemo &
to use disown:
Код:
paolor@debian-9:˜$ ./ConsoleDemo &
paolor@debian-9:˜$ disown
or if you forget to put your program in background:
Код:
paolor@debian-9:˜$ ./ConsoleDemo
paolor@debian-9:˜$ <Ctrl-Z>
paolor@debian-9:˜$ bg
paolor@debian-9:˜$ disown
other differences:
- disown doesn't redirect stdout/stderr so you have no way to see messages possibly sent to the (original) shell
- nohup redirect stdout/stderr to nohup.out file, so you can type tail nohup.out to see your messages
- nohup is defined by POSIX while disown is not, this means that some shell have it, some have not.
Для просмотра ссылки Войди
Conclusions
In this article we explored the options for launching our (standard) console application (that must behave as a service) in Linux and the preferred way seems to be the nohup command. This solution works but a real Linux daemon is by far the better way to deploy "services" on the Linux platform and even more so is the "official" way in UNIX OSes but to be able to build a daemon in Delphi you have to wait the next article, stay tuned!
[/SHOWTOGROUPS]