Allow multiple service instances on Windows.

pull/2346/head
Roger A. Light 4 years ago
parent 91e8344a3e
commit f0ed872786

@ -82,6 +82,8 @@ Broker:
client connects with the same client id. Closes #2340.
- Add support for sending the SIGRTMIN signal to trigger log rotation.
Closes #2337.
- Allow multiple instances of mosquitto to run as services on Windows. See
README-windows.txt.
Client library:
- Add MOSQ_OPT_DISABLE_SOCKETPAIR to allow the disabling of the socketpair

@ -21,7 +21,8 @@ start/stop it from the control panel as well as running it as a normal
executable.
When running as a service, the configuration file used is mosquitto.conf in the
directory that you installed to.
directory defined by the %MOSQUITTO_DIR% environment variable. This will be set
to the directory that you installed to by default.
If you want to install/uninstall mosquitto as a Windows service run from the
command line as follows:
@ -29,6 +30,24 @@ command line as follows:
C:\Program Files\mosquitto\mosquitto install
C:\Program Files\mosquitto\mosquitto uninstall
It is possible to install and run multiple instances of a Mosquitto service, as
of version 2.1. To do this, copy the mosquitto executable to a new *name* and
run the service install as above. The service will load a configuration file
mosquitto.conf from the directory defined by the environment variable
"<executable_name>_DIR". For this reason it is suggested to keep the executable
name consisting of alphanumeric and '_' characters. Any other character will be
replaced with '_'.
For example, if you copy mosquitto.exe to eclipse_mosquitto.exe, you would run
these commands to install/uninstall:
C:\Program Files\mosquitto\eclipse_mosquitto install
C:\Program Files\mosquitto\eclipse_mosquitto uninstall
And the service would try to load the config file at %ECLIPSE_MOSQUITTO_DIR%/mosquitto.conf
The new service will appear in the service list as "Mosquitto Broker (eclipse_mosquitto.exe)".
Logging
-------

@ -225,13 +225,13 @@ int main(int argc, char *argv[])
#if defined(WIN32) || defined(__CYGWIN__)
if(argc == 2){
if(!strcmp(argv[1], "run")){
service_run();
service_run(argv[0]);
return 0;
}else if(!strcmp(argv[1], "install")){
service_install();
service_install(argv[0]);
return 0;
}else if(!strcmp(argv[1], "uninstall")){
service_uninstall();
service_uninstall(argv[0]);
return 0;
}
}

@ -902,9 +902,9 @@ void signal__flag_check(void);
* Window service and signal related functions
* ============================================================ */
#if defined(WIN32) || defined(__CYGWIN__)
void service_install(void);
void service_uninstall(void);
void service_run(void);
void service_install(char *name);
void service_uninstall(char *name);
void service_run(char *name);
DWORD WINAPI SigThreadProc(void* data);
#endif

@ -20,8 +20,8 @@ Contributors:
#include "config.h"
#include "mosquitto_broker_internal.h"
#include <windows.h>
#include "memory_mosq.h"
extern int g_run;
@ -29,6 +29,21 @@ SERVICE_STATUS_HANDLE service_handle = 0;
static SERVICE_STATUS service_status;
int main(int argc, char *argv[]);
static char* fix_name(char* name)
{
size_t len;
if (strrchr(name, '\\')) {
name = strrchr(name, '\\') + 1;
}
len = strlen(name);
if(!strcasecmp(&name[len-4], ".exe")){
name[len-4] = '\0';
}
return name;
}
static void print_error(void)
{
char *buf = NULL;
@ -69,23 +84,39 @@ void __stdcall service_main(DWORD dwArgc, LPTSTR *lpszArgv)
int argc = 1;
char conf_path[MAX_PATH + 20];
int rc;
char *name;
char env_name[MAX_PATH];
UNUSED(dwArgc);
UNUSED(lpszArgv);
service_handle = RegisterServiceCtrlHandler("mosquitto", service_handler);
name = fix_name(lpszArgv[0]);
snprintf(env_name, sizeof(env_name), "%s_DIR", name);
for(int i=0; i<strlen(env_name); i++) {
if(env_name[i]>='A' && env_name[i]<='Z') {
/* Keep upper case letter */
}else if(env_name[i]>='0' && env_name[i]<='9'){
/* Keep number */
}else if(env_name[i]>='a' && env_name[i]<='z'){
/* Convert lower case to upper case */
env_name[i] -= 32;
}else{
env_name[i] = '_';
}
}
service_handle = RegisterServiceCtrlHandler(name, service_handler);
if(service_handle){
memset(conf_path, 0, sizeof(conf_path));
rc = GetEnvironmentVariable("MOSQUITTO_DIR", conf_path, MAX_PATH);
rc = GetEnvironmentVariable(env_name, conf_path, MAX_PATH);
if(!rc || rc == MAX_PATH){
service_status.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(service_handle, &service_status);
return;
}
strcat(conf_path, "/mosquitto.conf");
strcat(conf_path, "\\mosquitto.conf");
argv = mosquitto__malloc(sizeof(char *)*3);
argv[0] = "mosquitto";
argv[0] = name;
argv[1] = "-c";
argv[2] = conf_path;
argc = 3;
@ -105,11 +136,12 @@ void __stdcall service_main(DWORD dwArgc, LPTSTR *lpszArgv)
}
}
void service_install(void)
void service_install(char* name)
{
SC_HANDLE sc_manager, svc_handle;
char service_string[MAX_PATH + 20];
char exe_path[MAX_PATH + 1];
char display_name[MAX_PATH+1];
SERVICE_DESCRIPTION svc_desc;
memset(exe_path, 0, sizeof(exe_path));
@ -119,14 +151,23 @@ void service_install(void)
}
snprintf(service_string, sizeof(service_string), "\"%s\" run", exe_path);
name = fix_name(name);
sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
if(sc_manager){
svc_handle = CreateService(sc_manager, "mosquitto", "Mosquitto Broker",
if (!strcmp(name, "mosquitto")) {
snprintf(display_name, sizeof(display_name), "Mosquitto Broker");
}else{
snprintf(display_name, sizeof(display_name), "Mosquitto Broker (%s.exe)", name);
}
svc_handle = CreateService(sc_manager, name, display_name,
SERVICE_START | SERVICE_STOP | SERVICE_CHANGE_CONFIG,
SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
service_string, NULL, NULL, NULL, NULL, NULL);
if(svc_handle){
memset(&svc_desc, 0, sizeof(svc_desc));
svc_desc.lpDescription = "Eclipse Mosquitto MQTT v5/v3.1.1 broker";
ChangeServiceConfig2(svc_handle, SERVICE_CONFIG_DESCRIPTION, &svc_desc);
CloseServiceHandle(svc_handle);
@ -139,14 +180,16 @@ void service_install(void)
}
}
void service_uninstall(void)
void service_uninstall(char *name)
{
SC_HANDLE sc_manager, svc_handle;
SERVICE_STATUS status;
name = fix_name(name);
sc_manager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
if(sc_manager){
svc_handle = OpenService(sc_manager, "mosquitto", SERVICE_QUERY_STATUS | DELETE);
svc_handle = OpenService(sc_manager, name, SERVICE_QUERY_STATUS | DELETE);
if(svc_handle){
if(QueryServiceStatus(svc_handle, &status)){
if(status.dwCurrentState == SERVICE_STOPPED){
@ -163,14 +206,15 @@ void service_uninstall(void)
}
}
void service_run(void)
void service_run(char *name)
{
SERVICE_TABLE_ENTRY ste[] = {
{ "mosquitto", service_main },
{ name, service_main },
{ NULL, NULL }
};
name = fix_name(name);
ste[0].lpServiceName = name;
StartServiceCtrlDispatcher(ste);
}
#endif
#endif
Loading…
Cancel
Save