要实现Linux下kbmmw 服务器的开机自动启动,必须使用linux daemon 技术,此项技术的实现具体可以通过网上查询,
今天主要写一下具体实现方式,Linux daemon的实现方法很多,但是都有一些不尽人意的问题,最近在Github 发现了一个
实现方式,经过测试发现,比较完美的实现了Linux daemon的开发。
https://github.com/EvgeniyKorepov/LinuxDaemonNewStyle
我们首先下载文件保存。
使用delphi 10.3.3 建立一个控制台工程,添加一个TDataModule,放置我们常规的kbmmw server等控件。
添加kbmmw smartservice.
加入刚才下载的两个文件。工程文件如图
另存工程名为 Linuxdaemon.
修改UnitDaemonNewStyle.pas 文件。
我是ubuntu 20.4,这一块修改为/var/run/ . 切记修改。
整个工程源码如下
program Linuxdaemon; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, kbmMWConfiguration, kbmMWCrossSockethttpServerTransport, kbmMWTCPServerTransport, syscomm in 'syscomm.pas', dmp in 'dmp.pas' {dmf: TDataModule}, httpservice in 'httpservice.pas' {kbmMWCustomHTTPSmartService1: TkbmMWCustomHTTPSmartService}, Posix.Syslog in 'Posix.Syslog.pas', UnitDaemonNewStyle in 'UnitDaemonNewStyle.pas'; var AEvent : TEventType; procedure xalionserverstart; begin if not fileexists(homepath+'httpconfig.xml') then begin writeln('找不到配置文件:'+ homepath+'httpconfig.xml'); exit; end; { TODO -oUser -cConsole Main : Insert code here } syslog(LOG_NOTICE, 'KbmMW 应用服务器 '+vers); syslog(LOG_NOTICE, '操作系统:'+Tosversion.ToString); syslog(LOG_NOTICE, '内存: '+getservermemory); syslog(LOG_NOTICE, 'CPU: '+getcpuinfo(True)); syslog(LOG_NOTICE, '运行信息'+ GetApplicationName+' '+runinfor); dmf:=Tdmf.Create(nil); dmf.UniConnection1.Server :=config.AsDefString('database.server', '127.0.0.1'); dmf.UniConnection1.Database :=config.AsDefString('database.database', ''); dmf.UniConnection1.Username :=config.AsDefString('database.username', ''); dmf.UniConnection1.Password:=config.AsDefString('database.password', ''); dmf.UniConnection1.ProviderName:=config.AsDefString('database.providerName', 'oracle'); dmf.UniConnection1.Connect; if config.AsDefBoolean('tcptransport.open',False) then begin dmf.kbmMWTCPServerTransport1.Server :=dmf.kbmMWServer1; dmf.kbmMWTCPServerTransport1.Host:=config.AsDefString('tcptransport.host', '0.0.0.0'); dmf.kbmMWTCPServerTransport1.Port:=config.AsDefInt32('tcptransport.port', 4000); // dmf.kbmMWTCPServerTransport1.IOThreads:=100; syslog(LOG_NOTICE, 'TCP服务侦听在:'+ dmf.kbmMWTCPServerTransport1.Port.ToString); end; // TkbmMWTCPIPIndyServerTransport(dmf.RESTserverP).Bindings.Clear; with TkbmMWCrossSocketHttpServerTransport(dmf.RESTserverP) do begin host:=config.AsDefString('httptransportother.host', '0.0.0.0'); port:=config.AsDefInt32('httptransportother.port', 8080); end; dmf.kbmMWUNIDACConnectionPool1.MinConnections:=config.AsDefint32('databasepool.minnum',5); dmf.kbmMWUNIDACConnectionPool1.MaxConnections:=config.AsDefInt32('databasepool.maxnum',30); dmf.kbmMWServer1.AutoRegisterServices; dmf.kbmMWServer1.Active:=True; syslog(LOG_NOTICE, 'http服务侦听地址:'+TkbmMWCrossSocketHttpServerTransport(dmf.RESTserverP).host); syslog(LOG_NOTICE, 'http服务侦听端口:'+TkbmMWCrossSocketHttpServerTransport(dmf.RESTserverP).port.tostring); syslog(LOG_NOTICE, '使用UNIDAC 数据访问控件' ); syslog(LOG_NOTICE, '数据库类型:'+ dmf.UniConnection1.ProviderName); syslog(LOG_NOTICE, '数据库版本:'+ dmf.UniConnection1.ServerVersionFull); syslog(LOG_NOTICE, '数据库:'+ dmf.UniConnection1.Database); syslog(LOG_NOTICE, '数据库客户端版本:'+ dmf.UniConnection1.ClientVersion); syslog(LOG_NOTICE, '最大数据库连接池数:'+ dmf.kbmMWUNIDACConnectionPool1.MaxConnections.ToString ); syslog(LOG_NOTICE, '服务启动:'+formatdatetime('yyyy-mm-dd hh:nn:ss',now)); end; procedure xalionserverstop; begin dmf.kbmMWServer1.Active:=False; syslog(LOG_NOTICE, '服务停止:'+formatdatetime('yyyy-mm-dd hh:nn:ss',now)); end; procedure xalionserverrestart; begin xalionserverstop; xalionserverstart; end; begin if ParamCount = 0 then begin syslog(LOG_ERR, 'No parameters'); ExitCode := EXIT_FAILURE; exit; end; if ParamStr(1).ToLower.Equals('stop') then begin if Daemon.Stop(30) then ExitCode := EXIT_SUCCESS else ExitCode := EXIT_FAILURE; exit; end; if ParamStr(1).ToLower.Equals('reload') then begin if Daemon.Reload() then ExitCode := EXIT_SUCCESS else ExitCode := EXIT_FAILURE; exit; end; if not ParamStr(1).ToLower.Equals('start') then begin syslog(LOG_ERR, 'Unknow parameters'); ExitCode := EXIT_FAILURE; exit; end; syslog(LOG_NOTICE, 'main START'); while Daemon.IsRunning do begin syslog(LOG_NOTICE, 'main LOOP'); Daemon.Execute(AEvent); if AEvent <> TEventType.None then syslog(LOG_NOTICE, 'main Daemon receive signal'); case AEvent of TEventType.Start : begin // syslog(LOG_NOTICE, 'main Event START'); xalionserverstart; end; TEventType.Reload : begin // Reload config //syslog(LOG_NOTICE, 'main Event RELOAD'); xalionserverrestart; end; TEventType.Stop : begin ExitCode := EXIT_SUCCESS; Sleep(10); break; end; end; Sleep(1000); end; end.
编译此文件,并拷入/home/xalion/smartsrv 目录。
用root 权限建立一个服务描述文件 xalionserver.service。
内容为:
[Unit] Description=xalionserver service After=network.target [Service] Type=simple ExecStart=/home/xalion/smartsrv/Linuxdaemon start ExecReload=/home/xalion/smartsrv/Linuxdaemon reload ExecStop=/home/xalion/smartsrv/Linuxdaemon stop Restart=on-failure RestartSec=30 TimeoutStopSec=120 [Install] WantedBy=multi-user.target
保存。
进入/etc/systemd/system/
建立一个链接文件
sudo ln -s /home/xalion/smartsrv/xalionserver.service xalionserver.service
可以看到链接文件已经建立好了。
启动这个服务
sudo systemctl start xalionserver.service
我们去日志文件看看,是否正常运行
sudo nano /var/log/syslog
可以看到,所有的功能正常开始运行。
也可以查看服务运行状态
systemctl status xalionserver.service
我们使用浏览器访问
现在就剩下了自启动了。
在/etc/systemd/system/multi-user.target.want 目录下,建立同样的文件。
重新启动Linux 服务器。
直接在客户端打开浏览,一切都正常。
整个过程非常流畅。