Skip to content

Commit

Permalink
fix(winsvc): Optimize windows services checks
Browse files Browse the repository at this point in the history
Extra noticable when monitoring remote servers
  • Loading branch information
Göran Sander committed Dec 13, 2023
1 parent e9a1ff5 commit 47e08ad
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 103 deletions.
2 changes: 1 addition & 1 deletion src/lib/service_monitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ const verifyServicesExist = async (config, logger) => {

if (serviceExists) {
logger.verbose(
`VERIFY WIN SERVICES EXIST: Windows service ${service.name} (="${service.friendlyName}") on host ${host.host} exists: ${serviceExists}`
`VERIFY WIN SERVICES EXIST: Windows service ${service.name} (="${service.friendlyName}") on host ${host.host} exists.`
);
} else {
logger.error(
Expand Down
206 changes: 104 additions & 102 deletions src/lib/winsvc.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ function all(logger, host = null) {
.filter((line) => line.indexOf('SERVICE_NAME') !== -1)
.map((line) => line.replace('SERVICE_NAME: ', ''));

logger.verbose(`WINSVC ALL: Got all services on host ${host}`);
logger.verbose(lines);
logger.verbose(`WINSVC ALL: Got all ${lines.length} services on host ${host}`);
logger.debug(lines);

// Resolve with array of service names
resolveAll(lines);
Expand Down Expand Up @@ -291,6 +291,8 @@ function status(logger, serviceName, host = null) {

/**
* Get the details of provided service
* It is assumed that the service exists.
*
* @param {object} logger Logger object
* @param {string} serviceName Name of service
* @param {string} host Host on which service is running
Expand All @@ -307,121 +309,121 @@ function details(logger, serviceName, host = null) {
}

// Run check for service existance
logger.verbose(`WINSVC DETAILS: Checking if service ${serviceName} exists on host ${host}`);
exists(logger, serviceName, host).then(
// Existance check completed
(alreadyExists) => {
// Service exists
logger.verbose(`WINSVC DETAILS: Found! Service ${serviceName} exists on host ${host}`);

// If exists, reject
if (!alreadyExists) {
logger.verbose(`WINSVC DETAILS: Not found! Service ${serviceName} does not exists on host ${host}`);

reject(new Error(`Service with name '${serviceName}' does not exists`));
return;
}
// logger.verbose(`WINSVC DETAILS: Checking if service ${serviceName} exists on host ${host}`);
// exists(logger, serviceName, host).then(
// // Existance check completed
// (alreadyExists) => {
// // Service exists
// logger.verbose(`WINSVC DETAILS: Found! Service ${serviceName} exists on host ${host}`);

let command = '';
if (host === null) {
// Run command for get states of all services on local machine
logger.verbose(`WINSVC DETAILS: Getting details of service ${serviceName} on local machine`);
// // If exists, reject
// if (!alreadyExists) {
// logger.verbose(`WINSVC DETAILS: Not found! Service ${serviceName} does not exists on host ${host}`);

command = `sc.exe qc "${serviceName}"`;
} else {
// A host other that local machine is specfied
logger.verbose(`WINSVC DETAILS: Getting details of service ${serviceName} on host ${host}`);
// reject(new Error(`Service with name '${serviceName}' does not exists`));
// return;
// }

command = `sc.exe \\\\${host} qc "${serviceName}"`;
}
let command = '';
if (host === null) {
// Run command for get states of all services on local machine
logger.verbose(`WINSVC DETAILS: Getting details of service ${serviceName} on local machine`);

// Run command to get service details with provided data
logger.debug(`WINSVC DETAILS: Running command ${command}`);
exec(command, (err, stdout) => {
let i = 0;
const startTypeRegex = /\d/;
const dependenciesRegex = /(?<=\s*DEPENDENCIES)(\s*:.*\r\n)*/;

const deps = dependenciesRegex.exec(stdout)[0].toString().split('\r\n');

for (i = 0; i < deps.length; ) {
deps[i] = deps[i].replace(/\s*: /, '');
if (deps[i] === '') {
deps.splice(i, 1);
}
i += 1;
}
command = `sc.exe qc "${serviceName}"`;
} else {
// A host other that local machine is specfied
logger.verbose(`WINSVC DETAILS: Getting details of service ${serviceName} on host ${host}`);

// On error, reject and exit
if (err) {
logger.error(`WINSVC DETAILS: Error while getting details of service ${serviceName} on host ${host}`);
if (err.code) {
logger.error(`WINSVC DETAILS 1: Error code: ${err.code}`);
}
command = `sc.exe \\\\${host} qc "${serviceName}"`;
}

reject(err);
return;
}
// Run command to get service details with provided data
logger.debug(`WINSVC DETAILS: Running command ${command}`);
exec(command, (err, stdout) => {
let i = 0;
const startTypeRegex = /\d/;
const dependenciesRegex = /(?<=\s*DEPENDENCIES)(\s*:.*\r\n)*/;

const lines = stdout.toString().split('\r\n');
// Debug log lines
logger.debug(`WINSVC DETAILS: Lines: ${lines}`);

let startTypeName = '';

switch (startTypeRegex.exec(lines.find((line) => line.indexOf('START_TYPE') !== -1))[0]) {
case '2':
startTypeName = 'Automatic';
break;
case '3':
startTypeName = 'Manual';
break;
case '4':
startTypeName = 'Disabled';
break;
default:
return;
}
const deps = dependenciesRegex.exec(stdout)[0].toString().split('\r\n');

// Show all details that will be returned
logger.verbose(`WINSVC DETAILS: Service ${serviceName} is ${startTypeName} on host ${host}`);
logger.verbose(`WINSVC DETAILS: Service ${serviceName} has dependencies ${deps}`);
logger.verbose(
`WINSVC DETAILS: Service ${serviceName} has exe path ${lines
.find((line) => line.indexOf('BINARY_PATH_NAME') !== -1)
.replace(/\s*BINARY_PATH_NAME\s*: /, '')}`
);
logger.verbose(
`WINSVC DETAILS: Service ${serviceName} has display name ${lines
.find((line) => line.indexOf('DISPLAY_NAME') !== -1)
.replace(/\s*DISPLAY_NAME\s*: /, '')}`
);
logger.verbose(
`WINSVC DETAILS: Service ${serviceName} has name ${lines
.find((line) => line.indexOf('SERVICE_NAME: ') !== -1)
.replace('SERVICE_NAME: ', '')}`
);

resolve({
name: lines.find((line) => line.indexOf('SERVICE_NAME: ') !== -1).replace('SERVICE_NAME: ', ''),
displayName: lines.find((line) => line.indexOf('DISPLAY_NAME') !== -1).replace(/\s*DISPLAY_NAME\s*: /, ''),
startType: startTypeName,
exePath: lines.find((line) => line.indexOf('BINARY_PATH_NAME') !== -1).replace(/\s*BINARY_PATH_NAME\s*: /, ''),
dependencies: deps,
});
});
},
for (i = 0; i < deps.length; ) {
deps[i] = deps[i].replace(/\s*: /, '');
if (deps[i] === '') {
deps.splice(i, 1);
}
i += 1;
}

// Reject on error
(err) => {
// On error, reject and exit
if (err) {
logger.error(`WINSVC DETAILS: Error while getting details of service ${serviceName} on host ${host}`);
if (err.code) {
logger.error(`WINSVC DETAILS 2: Error code: ${err.code}`);
logger.error(`WINSVC DETAILS 1: Error code: ${err.code}`);
}

reject(err);
return;
}
);

const lines = stdout.toString().split('\r\n');
// Debug log lines
logger.debug(`WINSVC DETAILS: Lines: ${lines}`);

let startTypeName = '';

switch (startTypeRegex.exec(lines.find((line) => line.indexOf('START_TYPE') !== -1))[0]) {
case '2':
startTypeName = 'Automatic';
break;
case '3':
startTypeName = 'Manual';
break;
case '4':
startTypeName = 'Disabled';
break;
default:
return;
}

// Show all details that will be returned
logger.verbose(`WINSVC DETAILS: Service ${serviceName} is ${startTypeName} on host ${host}`);
logger.verbose(`WINSVC DETAILS: Service ${serviceName} has dependencies ${deps}`);
logger.verbose(
`WINSVC DETAILS: Service ${serviceName} has exe path ${lines
.find((line) => line.indexOf('BINARY_PATH_NAME') !== -1)
.replace(/\s*BINARY_PATH_NAME\s*: /, '')}`
);
logger.verbose(
`WINSVC DETAILS: Service ${serviceName} has display name ${lines
.find((line) => line.indexOf('DISPLAY_NAME') !== -1)
.replace(/\s*DISPLAY_NAME\s*: /, '')}`
);
logger.verbose(
`WINSVC DETAILS: Service ${serviceName} has name ${lines
.find((line) => line.indexOf('SERVICE_NAME: ') !== -1)
.replace('SERVICE_NAME: ', '')}`
);

resolve({
name: lines.find((line) => line.indexOf('SERVICE_NAME: ') !== -1).replace('SERVICE_NAME: ', ''),
displayName: lines.find((line) => line.indexOf('DISPLAY_NAME') !== -1).replace(/\s*DISPLAY_NAME\s*: /, ''),
startType: startTypeName,
exePath: lines.find((line) => line.indexOf('BINARY_PATH_NAME') !== -1).replace(/\s*BINARY_PATH_NAME\s*: /, ''),
dependencies: deps,
});
});
// },

// // Reject on error
// (err) => {
// logger.error(`WINSVC DETAILS: Error while getting details of service ${serviceName} on host ${host}`);
// if (err.code) {
// logger.error(`WINSVC DETAILS 2: Error code: ${err.code}`);
// }

// reject(err);
// }
// );
});
}

Expand Down

0 comments on commit 47e08ad

Please sign in to comment.