Services
Services are long-running applications designed to run in the background without user intervention and that are started automatically when the OS boots. InstallBuilder includes some actions to manage Windows and Linux services.
Linux Services
-
<addUnixService>
: This action allow users to add services to the system:
<addUnixService>
<program>/path/to/script</program>
<name>myservice</name>
</addUnixService>
The provided <program>
must be a valid init script. As a basic example of code you could use is:
#!/sbin/sh
# chkconfig: 235 30 90
# description: your description
start () {
# Put here the command to start your application
}
stop () {
# Put here the command to stop your application
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
sleep 1
start
;;
*)
echo "Usage: $0 { start | stop | restart }"
exit 1
;;
esac
exit 0
You can find other examples under /etc/init.d/
in a Linux installation.
-
<removeUnixService>
: This action allows you remove an existing service:
<removeUnixService>
<name>myservice</name>
</removeUnixService>
Windows Services
-
<createWindowsService>
: This action allows users to add services to the system:
<createWindowsService>
<program>${installdir}/myapp.exe</program>
<programArguments></programArguments>
<serviceName>myservice</serviceName>
<displayName>My Service</displayName>
<startType>auto</startType>
<description>My Sample Service</description>
<dependencies></dependencies>
<account></account>
<password></password>
</createWindowsService>
This will cause a service identified by <serviceName>
and with display name <displayName>
to be created.
When starting, myapp.exe
will be run from the application installation directory.
<startType>
specifies that the service should be started along with operating system. It takes one of the following values:
-
auto - automatically start the service when the operating system is restarted.
-
manual - service does not start with the operating system, but can be manually started from the control panel and using the API
-
disabled - service does not start with the operating system and it cannot be manually started from the control panel or using the API.
By default, the service will be run as the system
user. In order to run the service under a specific account, the <account>
and <password>
fields need to contain a valid user and password.
-
<deleteWindowsService>
: This action removes an existing service.
<deleteWindowsService>
<serviceName>myservice</serviceName>
<displayName>My Service</displayName>
</deleteWindowsService>
Deletes the service identified by <serviceName>
and with the display name <displayName>
. Both fields are used for identification of services on Microsoft Windows.
A service is stopped before deletion if it is currently running.
-
<startWindowsService>
: This action allows starting an existing service.
<startWindowsService>
<serviceName>myservice</serviceName>
<displayName>My Service</displayName>
<delay>15000</delay>
</startWindowsService>
Starts the service identified by <serviceName>
and with the display name <displayName>
. Both fields are used for identification of services on Microsoft Windows.
<delay>
specifies the number of milliseconds to wait for the service to start.
-
<stopWindowsService>
: This action allows stopping an existing service:
<stopWindowsService>
<serviceName>myservice</serviceName>
<displayName>My Service</displayName>
<delay>15000</delay>
</stopWindowsService>
<delay>
specifies amount of milliseconds to wait for the service to stop.
-
<restartWindowsService>
: This action allows restarting an existing service:
<restartWindowsService>
<serviceName>myservice</serviceName>
<displayName>My Service</displayName>
<delay>15000</delay>
</restartWindowsService>
Stops service identified by <serviceName>
and with display name <displayName>
. Both fields are used for identification of services on Microsoft Windows.
<delay>
specifies amount of milliseconds to wait for the service to stop and start.
InstallBuilder also provides a rule to check the status/existence of Windows services, <windowsServiceTest>
. This can be used for example to create a service, but only if it does not already exist:
<createWindowsService>
<program>${installdir}/myService.exe</program>
<programArguments></programArguments>
<serviceName>myservice</serviceName>
<displayName>My Service</displayName>
<startType>auto</startType>
<description>My Service</description>
<dependencies></dependencies>
<account>my_account</account>
<password>mySecRetPassword!!</password>
<ruleList>
<windowsServiceTest service="myservice" condition="not_exists"/>
</ruleList>
</createWindowsService>
InstallBuilder also provides an automatic way of generating unique Windows service names following a specified pattern. This is useful for situations in which you need to install multiple services.
<getUniqueWindowsServiceName>
<serviceName>foo</serviceName>
<displayName>My Foo service</displayName>
<selectedDisplayNameVariable>newDisplayName</selectedDisplayNameVariable>
<selectedServiceNameVariable>newServiceName</selectedServiceNameVariable>
</getUniqueWindowsServiceName>
<createWindowsService>
<program>${installdir}/myService.exe</program>
<programArguments></programArguments>
<serviceName>${newServiceName}</serviceName>
<displayName>${newDisplayName}</displayName>
<startType>auto</startType>
<description>My Service</description>
<dependencies></dependencies>
<account>my_account</account>
<password>mySecRetPassword!!</password>
</createWindowsService>
If the service foo
already exists, InstallBuilder will pick a new service name, foo-1
, if that is taken as well, foo-2
, foo-3
and so on… until a valid unique name is found, storing the new
names in the provided <selectedDisplayNameVariable>
and <selectedServiceNameVariable>
.
Using regular binaries as Windows services
Services in Microsoft Windows require binaries created especially for running as a service and need to properly support being stopped, started, paused and resumed.
In some cases it is necessary to run binaries that were not created for running as a service. It is possible to use third party tools to run applications as services. This way any application or script can be used as a Windows service. There are multiple solutions for running any application as a script. Microsoft provides srvany.exe
tool that can be used for creating services from any application. It is described on Microsoft’s website: https://support.microsoft.com/kb/137890. The binary simply runs itself as a service and starts application as child process. However, srvany
cannot be easily redistributed due to licensing issues.
Another tool is nssm.exe
. It is a single file application that can be redistributed with your installer. The binary can be downloaded from https://nssm.cc/.
The first step is to add nssm.exe
to the installer’s payload. It can be done as part of existing component or as new component:
<component>
<name>nssm</name>
<description>nssm</description>
<canBeEdited>0</canBeEdited>
<selected>1</selected>
<show>0</show>
<folderList>
<folder>
<description>nssm</description>
<destination>${installdir}</destination>
<name>nssm</name>
<platforms>windows</platforms>
<distributionFileList>
<distributionFile>
<origin>/path/to/nssm.exe</origin>
</distributionFile>
</distributionFileList>
</folder>
</folderList>
</component>
The next step is to add actions to the post-installation step that creates a service. The service name is set to the servicename variable. The nssm.exe install "${servicename}" "${installdir}/myapp.exe"
command creates and runs the service. Finally the nssm.exe set "${servicename}" Start "SERVICE_AUTO_START"
command sets the value for a service pararameter, in this case the service’s startup type.
<postInstallationActionList>
<setInstallerVariable>
<name>servicename</name>
<persist>1</persist>
<value>IBSampleService</value>
</setInstallerVariable>
<runProgram>
<runAs>Administrator</runAs>
<program>${installdir}/nssm.exe</program>
<programArguments>install "${servicename}" "${installdir}/myapp.exe"</programArguments>
<workingDirectory>${installdir}</workingDirectory>
</runProgram>
<runProgram>
<runAs>Administrator</runAs>
<program>${installdir}/nssm.exe</program>
<programArguments>start "${servicename}" "SERVICE_AUTO_START"</programArguments>
<workingDirectory>${installdir}</workingDirectory>
</runProgram>
</postInstallationActionList>
When the application is uninstalled, <deleteWindowsService>
needs to be called to delete the service.
<preUninstallationActionList>
<deleteWindowsService>
<abortOnError>0</abortOnError>
<displayName></displayName>
<serviceName>${servicename}</serviceName>
</deleteWindowsService>
</preUninstallationActionList>
OS X Services
-
<createOSXService>
: This action allows users to add services to the system:
<createOSXService>
<groupname>wheel</groupname>
<username>daemon</username>
<program>${installdir}/myService.run</program>
<programArguments></programArguments>
<scope>user</scope>
<serviceName>myService</serviceName>
</createOSXService>
-
<deleteOSXService>
: This action allows removing an existing service:
<deleteOSXService>
<serviceName>myService</serviceName>
</deleteOSXService>
Deletes a service on Mac OS X identified by <serviceName>, which contains the unique identifier of services for Mac OS X. The service is stopped before deletion if it is currently running.
-
<stopOSXService>
: This action allows stopping an existing service:
<stopOSXService>
<serviceName>myService</serviceName>
</stopOSXService>
This stops service on Mac OS X identified as serviceName. It is the unique identifier of services for Mac OS X.
-
<startOSXService>
: This action allows starting an existing service:
<startOSXService>
<serviceName>myService</serviceName>
</startOSXService>
This starts service on Mac OS X identified as serviceName. It is the unique identifier of services for Mac OS X.
Note
|
OS X service management actions are only supported from OS X 10.4 and newer |
Note
|
As a prerequisite, the program to be registered as a service must be compiled to run as a daemon |
InstallBuilder also provides a rule to check the status of OS X services, <osxServiceTest>:
<stopOSXService>
<serviceName>myService</serviceName>
<ruleList>
<osxServiceTest service="myService" condition="is_running"/>
</ruleList>
</stopOSXService>
Adding an Application to the System Startup
There are multiple ways of launching an application at startup on OS X, and it can vary from version to version of the operating system. This section describes the most general/compatible ones:
-
Changing the user Preferences files: This is the approach followed when manually adding an application to the Startup items. To do this, add a new entry to the
~/Library/Preferences/loginwindow.plist
file with the below format:
<plist version="1.0"> <dict> <key>Label</key> <string>nameOfTheEntry</string> <key>ProgramArguments</key> <array> <string>/some/path/to/the/program.run</string> <string>/Applications/InstallBuilder for Qt 7.2.5/autoupdate/runtimes/autoupdate-osx.a\ pp</string> </array> <key>KeepAlive</key> <true/> <key>Hide</key> <true/> <key>RunAtLoad</key> <true/> </dict> </plist>
-
Creating a
launchd
daemon: This approach is the preferred one when you do not have to support OS X versions below 10.4. Using this method you still need to create a .plist file in the same format as the one described in the previous method. Once you have it created, you just have to move it to/Library/LaunchDaemons/
:
$> sudo cp startup.plist /Library/LaunchDaemons/com.yourCompany.yourProgram.plist
Following the same naming in the target file is important to avoid conflicts in the future.
After restarting the machine, the new process should be running.
The code to automate this method in InstallBuilder would be:
<writeFile>
<path>${system_temp_directory}/your.plist</path>
<encoding>utf-8</encoding>
<text><![CDATA[
<plist version="1.0">
<dict>
<key>Label</key>
<string>nameOfTheEntry</string>
<key>ProgramArguments</key>
<array>
<string>/some/path/to/the/program.run</string>
<string>/Applications/InstallBuilder for Qt 7.2.5/autoupdate/runtimes/autoupdate-osx.app</string>
</array>
<key>KeepAlive</key>
<true/>
<key>Hide</key>
<true/>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
]]></text>
</writeFile>
<copyFile>
<origin>${system_temp_directory}/your.plist</origin>
<destination>/Library/LaunchDaemons/com.yourCompany.yourProgram.plist</destination>
</copyFile>
-
Creating a Startup Item: If your application requires compatibility with OS X 10.3 and earlier, this is the only available approach. The steps to follow are:
Create a directory under /Library/StartupItems
with the name of the startup item:
$> sudo mkdir /Library/StartupItems/yourItem
Create an executable with the same name of the directory. This executable can be just a bash script wrapping the your binary:
$> sudo touch /Library/StartupItems/yourItem/yourItem
The yourItem
script should implement the below functions (you can leave the body blank if they are not applicable to your startup item):
#!/bin/sh
. /etc/rc.common
StartService ()
{
/Applications/yourApplication-1.0/ctl.sh start
}
StopService ()
{
/Applications/yourApplication-1.0/ctl.sh stop
}
RestartService ()
{
/Applications/yourApplication-1.0/ctl.sh graceful
}
RunService "$1"
Create a .plist file named StartupParameters.plist
with some information about your item:
<plist version="1.0"> <dict> <key>Description</key> <string>My Application v1.0</string> <key>OrderPreference</key> <string>None</string> <key>Provides</key> <array> <string>yourItem</string> </array> </dict> </plist>
It can be tested by executing:
$> sudo /sbin/SystemStarter start "yourItem"