mirror of
https://github.com/Ylianst/MeshAgent
synced 2025-12-15 15:53:55 +00:00
1. Unified service type detection, between native and JS
2. Added basic support for pseudo services
This commit is contained in:
@@ -620,16 +620,6 @@ int MeshAgent_GetSystemProxy(MeshAgentHostContainer *agent, char *buffer, size_t
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef _POSIX
|
#ifdef _POSIX
|
||||||
typedef enum MeshAgent_Posix_PlatformTypes
|
|
||||||
{
|
|
||||||
MeshAgent_Posix_PlatformTypes_UNKNOWN = 0,
|
|
||||||
MeshAgent_Posix_PlatformTypes_SYSTEMD = 1,
|
|
||||||
MeshAgent_Posix_PlatformTypes_INITD = 2,
|
|
||||||
MeshAgent_Posix_PlatformTypes_INIT_UPSTART =4,
|
|
||||||
MeshAgent_Posix_PlatformTypes_LAUNCHD = 3,
|
|
||||||
MeshAgent_Posix_PlatformTypes_BSD = 5
|
|
||||||
}MeshAgent_Posix_PlatformTypes;
|
|
||||||
|
|
||||||
size_t MeshAgent_Linux_ReadMemFile(char *path, char **buffer)
|
size_t MeshAgent_Linux_ReadMemFile(char *path, char **buffer)
|
||||||
{
|
{
|
||||||
size_t i = 0, r, sz = 4096;
|
size_t i = 0, r, sz = 4096;
|
||||||
@@ -652,59 +642,7 @@ size_t MeshAgent_Linux_ReadMemFile(char *path, char **buffer)
|
|||||||
}
|
}
|
||||||
return(i);
|
return(i);
|
||||||
}
|
}
|
||||||
MeshAgent_Posix_PlatformTypes MeshAgent_Posix_GetPlatformType()
|
|
||||||
{
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
return(MeshAgent_Posix_PlatformTypes_LAUNCHD);
|
|
||||||
#elif defined(_FREEBSD)
|
|
||||||
return(MeshAgent_Posix_PlatformTypes_BSD);
|
|
||||||
#else
|
|
||||||
MeshAgent_Posix_PlatformTypes retVal = MeshAgent_Posix_PlatformTypes_UNKNOWN, fini = 0;
|
|
||||||
char *status;
|
|
||||||
size_t statusLen = MeshAgent_Linux_ReadMemFile("/proc/1/status", &status);
|
|
||||||
if (statusLen > 0)
|
|
||||||
{
|
|
||||||
parser_result *result = ILibParseString(status, 0, (int)statusLen, "\n", 1), *tokens;
|
|
||||||
parser_result_field *rf = result->FirstResult;
|
|
||||||
while (rf != NULL && fini == 0)
|
|
||||||
{
|
|
||||||
tokens = ILibParseString(rf->data, 0, rf->datalength, ":", 1);
|
|
||||||
if (tokens->NumResults == 2)
|
|
||||||
{
|
|
||||||
if (tokens->FirstResult->datalength == 4 && strncasecmp(tokens->FirstResult->data, "name", 4) == 0)
|
|
||||||
{
|
|
||||||
int tlen = tokens->LastResult->datalength;
|
|
||||||
char *tstr = tokens->LastResult->data;
|
|
||||||
tlen = ILibTrimString(&tstr, tlen);
|
|
||||||
if (tlen == 7 && strncasecmp(tstr, "systemd", 5) == 0)
|
|
||||||
{
|
|
||||||
retVal = MeshAgent_Posix_PlatformTypes_SYSTEMD;
|
|
||||||
}
|
|
||||||
else if (tlen == 4 && strncasecmp(tstr, "init", 4) == 0)
|
|
||||||
{
|
|
||||||
struct stat result;
|
|
||||||
memset(&result, 0, sizeof(struct stat));
|
|
||||||
if (stat("/etc/init", &result) != 0)
|
|
||||||
{
|
|
||||||
retVal = MeshAgent_Posix_PlatformTypes_INITD;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
retVal = MeshAgent_Posix_PlatformTypes_INIT_UPSTART;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fini = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ILibDestructParserResults(tokens);
|
|
||||||
rf = rf->NextResult;
|
|
||||||
}
|
|
||||||
ILibDestructParserResults(result);
|
|
||||||
free(status);
|
|
||||||
}
|
|
||||||
return(retVal);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
int MeshAgent_Helper_CommandLine(char **commands, char **result, int *resultLen)
|
int MeshAgent_Helper_CommandLine(char **commands, char **result, int *resultLen)
|
||||||
{
|
{
|
||||||
int bytesRead, x;
|
int bytesRead, x;
|
||||||
@@ -767,78 +705,6 @@ int MeshAgent_Helper_CommandLine(char **commands, char **result, int *resultLen)
|
|||||||
waitpid(pid, &bytesRead, 0);
|
waitpid(pid, &bytesRead, 0);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
int MeshAgent_Helper_IsService()
|
|
||||||
{
|
|
||||||
char *result = NULL;
|
|
||||||
int resultLen = 0;
|
|
||||||
char pidStr[255];
|
|
||||||
int pidStrLen = sprintf_s(pidStr, sizeof(pidStr), "%d", (int)getpid());
|
|
||||||
int retVal = 0;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
switch (MeshAgent_Posix_GetPlatformType())
|
|
||||||
{
|
|
||||||
case MeshAgent_Posix_PlatformTypes_SYSTEMD: // Linux Systemd
|
|
||||||
if (MeshAgent_Helper_CommandLine((char*[]) { "systemctl status meshagent | grep 'Main PID:' | awk '{print $3}'\n", "exit\n", NULL }, &result, &resultLen) == 0)
|
|
||||||
{
|
|
||||||
while (i<resultLen && result[i] != 10) { ++i; }
|
|
||||||
resultLen = i;
|
|
||||||
if (resultLen == pidStrLen && strncmp(result, pidStr, resultLen) == 0)
|
|
||||||
{
|
|
||||||
retVal = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MeshAgent_Posix_PlatformTypes_INITD:
|
|
||||||
if (MeshAgent_Helper_CommandLine((char*[]) { "service meshagent status | awk '{print $4}'\n", "exit\n", NULL }, &result, &resultLen) == 0)
|
|
||||||
{
|
|
||||||
while (i<resultLen && result[i] != 10) { ++i; }
|
|
||||||
resultLen = i;
|
|
||||||
if (resultLen == pidStrLen && strncmp(result, pidStr, resultLen) == 0)
|
|
||||||
{
|
|
||||||
retVal = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MeshAgent_Posix_PlatformTypes_INIT_UPSTART:
|
|
||||||
if (MeshAgent_Helper_CommandLine((char*[]) { "initctl status meshagent | awk '{print $4}'\n", "exit\n", NULL }, &result, &resultLen) == 0)
|
|
||||||
{
|
|
||||||
while (i<resultLen && result[i] != 10) { ++i; }
|
|
||||||
resultLen = i;
|
|
||||||
if (resultLen == pidStrLen && strncmp(result, pidStr, resultLen) == 0)
|
|
||||||
{
|
|
||||||
retVal = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MeshAgent_Posix_PlatformTypes_LAUNCHD: // MacOS Launchd
|
|
||||||
if (MeshAgent_Helper_CommandLine((char*[]) { "launchctl list\n", "exit\n", NULL }, &result, &resultLen) == 0)
|
|
||||||
{
|
|
||||||
parser_result *pr = ILibParseString(result, 0, resultLen, "\n", 1), *p2;
|
|
||||||
parser_result_field *f = pr->FirstResult;
|
|
||||||
while (f != NULL)
|
|
||||||
{
|
|
||||||
if (f->datalength > 0)
|
|
||||||
{
|
|
||||||
p2 = ILibParseString(f->data, 0, f->datalength, "\t", 1);
|
|
||||||
if (p2->NumResults > 1 && p2->FirstResult->datalength == pidStrLen && strncmp(p2->FirstResult->data, pidStr, pidStrLen) == 0)
|
|
||||||
{
|
|
||||||
retVal = 1;
|
|
||||||
ILibDestructParserResults(p2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ILibDestructParserResults(p2);
|
|
||||||
}
|
|
||||||
f = f->NextResult;
|
|
||||||
}
|
|
||||||
ILibDestructParserResults(pr);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default: // Generic
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return(retVal);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _REMOTELOGGING
|
#ifdef _REMOTELOGGING
|
||||||
@@ -3973,6 +3839,18 @@ int MeshAgent_AgentMode(MeshAgentHostContainer *agentHost, int paramLen, char **
|
|||||||
#if !defined(MICROSTACK_NOTLS) || defined(_POSIX)
|
#if !defined(MICROSTACK_NOTLS) || defined(_POSIX)
|
||||||
duk_context *tmpCtx = ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx(0, 0, agentHost->chain, NULL, NULL, agentHost->exePath, NULL, NULL, NULL);
|
duk_context *tmpCtx = ILibDuktape_ScriptContainer_InitializeJavaScriptEngineEx(0, 0, agentHost->chain, NULL, NULL, agentHost->exePath, NULL, NULL, NULL);
|
||||||
duk_peval_string_noresult(tmpCtx, "require('linux-pathfix')();");
|
duk_peval_string_noresult(tmpCtx, "require('linux-pathfix')();");
|
||||||
|
|
||||||
|
agentHost->platformType = MeshAgent_Posix_PlatformTypes_UNKNOWN;
|
||||||
|
agentHost->JSRunningAsService = 0;
|
||||||
|
|
||||||
|
if (duk_peval_string(tmpCtx, "(function foo() { var f = require('service-manager').manager.getServiceType(); switch(f){case 'windows': return(10); case 'launchd': return(3); case 'freebsd': return(5); case 'systemd': return(1); case 'init': return(2); case 'upstart': return(4); default: return(0);}})()") == 0)
|
||||||
|
{
|
||||||
|
agentHost->platformType = (MeshAgent_Posix_PlatformTypes)duk_get_int(tmpCtx, -1);
|
||||||
|
}
|
||||||
|
if (duk_peval_string(tmpCtx, "require('service-manager').manager.getService(process.platform=='win32'?'Mesh Agent':'meshagent').isMe();") == 0)
|
||||||
|
{
|
||||||
|
agentHost->JSRunningAsService = duk_get_int(tmpCtx, -1);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(MICROSTACK_NOTLS)
|
#if !defined(MICROSTACK_NOTLS)
|
||||||
@@ -4765,39 +4643,35 @@ int MeshAgent_Start(MeshAgentHostContainer *agentHost, int paramLen, char **para
|
|||||||
CloseHandle(processInfo.hThread);
|
CloseHandle(processInfo.hThread);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (MeshAgent_Helper_IsService() != 0)
|
if (agentHost->JSRunningAsService != 0)
|
||||||
{
|
{
|
||||||
// We were started as a service
|
// We were started as a service
|
||||||
if (agentHost->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Service Check... [YES]"); }
|
if (agentHost->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Service Check... [YES]"); }
|
||||||
|
|
||||||
MeshAgent_Posix_PlatformTypes pt = MeshAgent_Posix_GetPlatformType();
|
|
||||||
if (pt != MeshAgent_Posix_PlatformTypes_UNKNOWN)
|
struct stat results;
|
||||||
|
stat(agentHost->exePath, &results); // This the mode of the current executable
|
||||||
|
chmod(updateFilePath, results.st_mode); // Set the new executable to the same mode as the current one.
|
||||||
|
|
||||||
|
|
||||||
|
if (agentHost->platformType == MeshAgent_Posix_PlatformTypes_BSD)
|
||||||
{
|
{
|
||||||
struct stat results;
|
// FreeBSD doesn't support hot-swapping the binary
|
||||||
stat(agentHost->exePath, &results); // This the mode of the current executable
|
if (agentHost->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Handing off to child to complete"); }
|
||||||
chmod(updateFilePath, results.st_mode); // Set the new executable to the same mode as the current one.
|
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s -exec \"var s=require('service-manager').manager.getService('meshagent');s.stop();require('fs').copyFileSync('%s', '%s');s.start();process.exit();\"", updateFilePath, updateFilePath, agentHost->exePath);
|
||||||
|
ignore_result(MeshAgent_System(ILibScratchPad));
|
||||||
if (pt == MeshAgent_Posix_PlatformTypes_BSD)
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "mv \"%s\" \"%s\"", updateFilePath, agentHost->exePath); // Move the update over our own executable
|
||||||
|
if (system(ILibScratchPad)) {}
|
||||||
|
switch (agentHost->platformType)
|
||||||
{
|
{
|
||||||
// FreeBSD doesn't support hot-swapping the binary
|
|
||||||
if (agentHost->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Handing off to child to complete"); }
|
|
||||||
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "%s -exec \"var s=require('service-manager').manager.getService('meshagent');s.stop();require('fs').copyFileSync('%s', '%s');s.start();process.exit();\"", updateFilePath, updateFilePath, agentHost->exePath);
|
|
||||||
ignore_result(MeshAgent_System(ILibScratchPad));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "mv \"%s\" \"%s\"", updateFilePath, agentHost->exePath); // Move the update over our own executable
|
|
||||||
if (system(ILibScratchPad)) {}
|
|
||||||
|
|
||||||
switch (pt)
|
|
||||||
{
|
|
||||||
#ifdef __APPLE__
|
|
||||||
case MeshAgent_Posix_PlatformTypes_LAUNCHD:
|
case MeshAgent_Posix_PlatformTypes_LAUNCHD:
|
||||||
if (agentHost->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Complete... [kickstarting service]"); }
|
if (agentHost->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Complete... [kickstarting service]"); }
|
||||||
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "launchctl kickstart -k system/meshagent"); // Restart the service
|
sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "launchctl kickstart -k system/meshagent"); // Restart the service
|
||||||
ignore_result(MeshAgent_System(ILibScratchPad));
|
ignore_result(MeshAgent_System(ILibScratchPad));
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case MeshAgent_Posix_PlatformTypes_SYSTEMD:
|
case MeshAgent_Posix_PlatformTypes_SYSTEMD:
|
||||||
if (agentHost->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Complete... [SYSTEMD should auto-restart]"); }
|
if (agentHost->logUpdate != 0) { ILIBLOGMESSSAGE("SelfUpdate -> Complete... [SYSTEMD should auto-restart]"); }
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -4814,7 +4688,6 @@ int MeshAgent_Start(MeshAgentHostContainer *agentHost, int paramLen, char **para
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,17 @@ typedef char JS_ENGINE_CONTEXT[16];
|
|||||||
|
|
||||||
#define ILibDuktape_MeshAgent_LoggedOnUsers "\xFF_MeshAgent_LoggedOnUsers"
|
#define ILibDuktape_MeshAgent_LoggedOnUsers "\xFF_MeshAgent_LoggedOnUsers"
|
||||||
|
|
||||||
|
typedef enum MeshAgent_Posix_PlatformTypes
|
||||||
|
{
|
||||||
|
MeshAgent_Posix_PlatformTypes_UNKNOWN = 0,
|
||||||
|
MeshAgent_Posix_PlatformTypes_SYSTEMD = 1,
|
||||||
|
MeshAgent_Posix_PlatformTypes_INITD = 2,
|
||||||
|
MeshAgent_Posix_PlatformTypes_INIT_UPSTART = 4,
|
||||||
|
MeshAgent_Posix_PlatformTypes_LAUNCHD = 3,
|
||||||
|
MeshAgent_Posix_PlatformTypes_BSD = 5,
|
||||||
|
MeshAgent_Posix_PlatformTypes_WINDOWS = 10
|
||||||
|
}MeshAgent_Posix_PlatformTypes;
|
||||||
|
|
||||||
typedef enum MeshCommand_AuthInfo_CapabilitiesMask
|
typedef enum MeshCommand_AuthInfo_CapabilitiesMask
|
||||||
{
|
{
|
||||||
MeshCommand_AuthInfo_CapabilitiesMask_DESKTOP = 0x01,
|
MeshCommand_AuthInfo_CapabilitiesMask_DESKTOP = 0x01,
|
||||||
@@ -214,6 +225,8 @@ typedef struct MeshAgentHostContainer
|
|||||||
int serverConnectionState;
|
int serverConnectionState;
|
||||||
int exitCode;
|
int exitCode;
|
||||||
int dbRetryCount;
|
int dbRetryCount;
|
||||||
|
MeshAgent_Posix_PlatformTypes platformType;
|
||||||
|
int JSRunningAsService;
|
||||||
#if defined(_WINSERVICE)
|
#if defined(_WINSERVICE)
|
||||||
int runningAsConsole;
|
int runningAsConsole;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1293,7 +1293,112 @@ function serviceManager()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw ('Unknown Service Platform: ' + platform);
|
// Peudo Service (meshDaemon)
|
||||||
|
if (require('fs').existsSync('/usr/local/mesh_daemons/' + name + '.service'))
|
||||||
|
{
|
||||||
|
ret.conf = '/usr/local/mesh_daemons/' + name + '.service';
|
||||||
|
ret.start = function start()
|
||||||
|
{
|
||||||
|
var child;
|
||||||
|
child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
|
||||||
|
child.stderr.on('data', function (c) { });
|
||||||
|
child.stdin.write('cat ' + this.conf + " | tr '\n' '~' | awk -F~ '{ wd=" + '""; parms=""; for(i=1;i<=NF;++i) { split($i, tok1, "="); if(tok1[1]=="workingDirectory") { wd=tok1[2];} if(tok1[1]=="parameters") { parms=tok1[2];} } printf "{ \\\"wd\\\": \\\"%s\\\", \\\"parms\\\": %s }", wd, parms }\'\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var info = JSON.parse(child.stdout.str.trim());
|
||||||
|
info.exePath = info.wd + '/' + info.parms.shift();
|
||||||
|
|
||||||
|
var options = { pidPath: info.wd + '/pid', logOutputs: false };
|
||||||
|
require('service-manager').manager.daemon(info.exePath, info.parms , options);
|
||||||
|
};
|
||||||
|
ret.stop = function stop()
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
|
||||||
|
child.stdin.write('cat /usr/local/mesh_daemons/' + name + '/pid \nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
process.kill(parseInt(child.stdout.str.trim()), 'SIGTERM');
|
||||||
|
}
|
||||||
|
catch(x)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ret.isMe = function isMe()
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
|
||||||
|
child.stdin.write('cat /usr/local/mesh_daemons/' + name + '/pid \nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
return (parseInt(child.stdout.str.trim()) == process.pid);
|
||||||
|
};
|
||||||
|
ret.appWorkingDirectory = function appWorkingDirectory()
|
||||||
|
{
|
||||||
|
var child;
|
||||||
|
child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
|
||||||
|
child.stderr.on('data', function (c) { });
|
||||||
|
child.stdin.write('cat ' + this.conf + " | tr '\n' '~' | awk -F~ '{ wd=" + '""; parms=""; for(i=1;i<=NF;++i) { split($i, tok1, "="); if(tok1[1]=="workingDirectory") { wd=tok1[2];} if(tok1[1]=="parameters") { parms=tok1[2];} } printf "{ \\\"wd\\\": \\\"%s\\\", \\\"parms\\\": %s }", wd, parms }\'\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var info = JSON.parse(child.stdout.str.trim());
|
||||||
|
return (info.wd);
|
||||||
|
};
|
||||||
|
ret.appLocation = function appLocation()
|
||||||
|
{
|
||||||
|
var child;
|
||||||
|
child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
|
||||||
|
child.stderr.on('data', function (c) { });
|
||||||
|
child.stdin.write('cat ' + this.conf + " | tr '\n' '~' | awk -F~ '{ wd=" + '""; parms=""; for(i=1;i<=NF;++i) { split($i, tok1, "="); if(tok1[1]=="workingDirectory") { wd=tok1[2];} if(tok1[1]=="parameters") { parms=tok1[2];} } printf "{ \\\"wd\\\": \\\"%s\\\", \\\"parms\\\": %s }", wd, parms }\'\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
|
||||||
|
var info = JSON.parse(child.stdout.str.trim());
|
||||||
|
return (info.wd + '/' + info.parms.shift());
|
||||||
|
};
|
||||||
|
ret.isRunning = function isRunning()
|
||||||
|
{
|
||||||
|
if(require('fs').existsSync('/usr/local/mesh_daemons/' + name + '/pid'))
|
||||||
|
{
|
||||||
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
|
||||||
|
child.stdin.write('cat /usr/local/mesh_daemons/' + name + '/pid \nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
var pid = child.stdout.str.trim();
|
||||||
|
|
||||||
|
child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
|
||||||
|
child.stdin.write('ps -p ' + pid + ' -o pid h\nexit\n');
|
||||||
|
child.waitExit();
|
||||||
|
if(child.stdout.str.trim() == pid)
|
||||||
|
{
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
require('fs').unlinkSync('/usr/local/mesh_daemons/' + name + '/pid');
|
||||||
|
}
|
||||||
|
catch(x)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw ('MeshDaemon (' + name + ') NOT FOUND');
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1676,9 +1781,29 @@ function serviceManager()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: // unknown platform service type
|
default: // Unknown Service Type, install as a Pseudo Service (MeshDaemon)
|
||||||
console.log('Unknown Service Platform Type: ' + options.servicePlatform);
|
if (!require('fs').existsSync('/usr/local/mesh_daemons/')) { require('fs').mkdirSync('/usr/local/mesh_daemons'); }
|
||||||
throw ('Unknown Service Platform Type: ' + options.servicePlatform);
|
if (!require('fs').existsSync('/usr/local/mesh_daemons/' + options.name)) { require('fs').mkdirSync('/usr/local/mesh_daemons/' + options.name); }
|
||||||
|
if (!require('fs').existsSync('/usr/local/mesh_daemons/daemon'))
|
||||||
|
{
|
||||||
|
require('fs').copyFileSync(process.execPath, '/usr/local/mesh_daemons/daemon');
|
||||||
|
require('fs').chmodSync('/usr/local/mesh_daemons/daemon', require('fs').statSync('/usr/local/mesh_daemons/daemon').mode | require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||||
|
}
|
||||||
|
require('fs').copyFileSync(options.servicePath, '/usr/local/mesh_daemons/' + options.name + '/' + options.target);
|
||||||
|
|
||||||
|
var m = require('fs').statSync('/usr/local/mesh_daemons/' + options.name + '/' + options.target).mode;
|
||||||
|
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||||
|
require('fs').chmodSync('/usr/local/mesh_daemons/' + options.name + '/' + options.target, m);
|
||||||
|
|
||||||
|
conf = require('fs').createWriteStream('/usr/local/mesh_daemons/' + options.name + '.service', { flags: 'wb' });
|
||||||
|
conf.write('workingDirectory=' + '/usr/local/mesh_daemons/' + options.name + '\n');
|
||||||
|
|
||||||
|
if(!options.parameters) {options.parameters = [];}
|
||||||
|
options.parameters.unshift(options.name);
|
||||||
|
conf.write('parameters=' + JSON.stringify(options.parameters) + '\n');
|
||||||
|
options.parameters.shift();
|
||||||
|
|
||||||
|
conf.end();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1996,84 +2121,99 @@ function serviceManager()
|
|||||||
{ }
|
{ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(process.platform == 'linux')
|
|
||||||
|
this.getServiceType = function getServiceType()
|
||||||
{
|
{
|
||||||
this.getServiceType = function getServiceType()
|
var platform = 'unknown';
|
||||||
|
switch(process.platform)
|
||||||
{
|
{
|
||||||
var platform = require('process-manager').getProcessInfo(1).Name;
|
case 'win32':
|
||||||
if (platform == "busybox")
|
platform = 'windows';
|
||||||
{
|
break;
|
||||||
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
case 'freebsd':
|
||||||
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
|
platform = 'freebsd';
|
||||||
child.stdin.write("ps -ax -o pid -o command | awk '{ if($1==\"1\") { $1=\"\"; split($0, res, \" \"); print res[2]; }}'\nexit\n");
|
break;
|
||||||
child.waitExit();
|
case 'darwin':
|
||||||
platform = child.stdout.str.trim();
|
platform = 'launchd';
|
||||||
}
|
break;
|
||||||
if (platform == 'init')
|
case 'linux':
|
||||||
{
|
platform = require('process-manager').getProcessInfo(1).Name;
|
||||||
if(require('fs').existsSync('/etc/init'))
|
if (platform == "busybox")
|
||||||
{
|
{
|
||||||
platform = 'upstart';
|
var child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||||
|
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
|
||||||
|
child.stdin.write("ps -ax -o pid -o command | awk '{ if($1==\"1\") { $1=\"\"; split($0, res, \" \"); print res[2]; }}'\nexit\n");
|
||||||
|
child.waitExit();
|
||||||
|
platform = child.stdout.str.trim();
|
||||||
}
|
}
|
||||||
}
|
if (platform == 'init')
|
||||||
switch(platform)
|
{
|
||||||
{
|
if (require('fs').existsSync('/etc/init'))
|
||||||
case 'init':
|
{
|
||||||
case 'upstart':
|
platform = 'upstart';
|
||||||
case 'systemd':
|
}
|
||||||
break;
|
}
|
||||||
default:
|
switch (platform)
|
||||||
platform = 'unknown';
|
{
|
||||||
break;
|
case 'init':
|
||||||
}
|
case 'upstart':
|
||||||
return (platform);
|
case 'systemd':
|
||||||
};
|
break;
|
||||||
}
|
default:
|
||||||
|
platform = 'unknown';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (platform);
|
||||||
|
};
|
||||||
|
|
||||||
function spawnDaemon(ret)
|
|
||||||
{
|
|
||||||
ret.child = require('child_process').execFile(process.execPath, ret.options._parms, ret.options);
|
|
||||||
if (!ret.child) { ret._reject('Error Spawning Process'); }
|
|
||||||
|
|
||||||
ret.child.promise = ret;
|
|
||||||
ret.child.stdout.on('data', function (c) { console.log(c.toString()); });
|
|
||||||
ret.child.stderr.on('data', function (c) { console.log(c.toString()); });
|
|
||||||
ret.child.on('exit', function (c)
|
|
||||||
{
|
|
||||||
if (this.promise.options.crashRestart)
|
|
||||||
{
|
|
||||||
spawnDaemon(this.promise);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.promise._accept('Finished');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.daemon = function daemon(path, parameters, options)
|
this.daemon = function daemon(path, parameters, options)
|
||||||
{
|
{
|
||||||
var ret = new promise(function (a, r) { this._accept = a; this._reject = r; });
|
|
||||||
var tmp = JSON.stringify(parameters);
|
var tmp = JSON.stringify(parameters);
|
||||||
tmp = tmp.substring(1, tmp.length - 1);
|
tmp = tmp.substring(1, tmp.length - 1);
|
||||||
|
|
||||||
if (!options) { options = {}; }
|
if (!options) { options = {}; }
|
||||||
ret.options = options;
|
var childParms = "\
|
||||||
|
var child = null; \
|
||||||
var childParms = ("var child = require('child_process').execFile('" + path + "', ['" + (process.platform == 'win32' ? path.split('\\').pop() : path.split('/').pop() + "'" + (tmp != '' ? (", " + tmp) : "")) + "]);\n");
|
var options = " + JSON.stringify(options) + ";\
|
||||||
childParms += "if(!child) {console.log('error'); process.exit();}\n";
|
if(options.logOutput) { console.setDestination(console.Destinations.LOGFILE); console.log('Logging Outputs...'); }\
|
||||||
childParms += "child.stdout.on('data', function(c){ console.log(c.toString()); });\n";
|
function cleanupAndExit()\
|
||||||
childParms += "child.stderr.on('data', function(c){ console.log(c.toString()); });\n";
|
{\
|
||||||
childParms += "child.on('exit', function(c){ process.exit(); });\n";
|
if(options.pidPath) { require('fs').unlinkSync(options.pidPath); }\
|
||||||
|
}\
|
||||||
|
function spawnChild()\
|
||||||
|
{\
|
||||||
|
child = require('child_process').execFile('" + path + "', ['" + (process.platform == 'win32' ? path.split('\\').pop() : path.split('/').pop() + "'" + (tmp != '' ? (", " + tmp) : "")) + "]);\
|
||||||
|
if(child)\
|
||||||
|
{\
|
||||||
|
child.stdout.on('data', function(c) { console.log(c.toString()); });\
|
||||||
|
child.stderr.on('data', function(c) { console.log(c.toString()); });\
|
||||||
|
child.once('exit', function (code) \
|
||||||
|
{\
|
||||||
|
if(options.crashRestart) { spawnChild(); } else { cleanupAndExit(); }\
|
||||||
|
});\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
if(options.pidPath) { require('fs').writeFileSync(options.pidPath, process.pid.toString()); }\
|
||||||
|
spawnChild();\
|
||||||
|
process.on('SIGTERM', function()\
|
||||||
|
{\
|
||||||
|
if(child) { child.kill(); }\
|
||||||
|
cleanupAndExit();\
|
||||||
|
process.exit();\
|
||||||
|
});";
|
||||||
|
|
||||||
var parms = [process.platform == 'win32' ? process.execPath.split('\\').pop() : process.execPath.split('/').pop()];
|
var parms = [process.platform == 'win32' ? process.execPath.split('\\').pop() : process.execPath.split('/').pop()];
|
||||||
parms.push('-b64exec');
|
parms.push('-b64exec');
|
||||||
parms.push(Buffer.from(childParms).toString('base64'));
|
parms.push(Buffer.from(childParms).toString('base64'));
|
||||||
ret.options._parms = parms;
|
options._parms = parms;
|
||||||
|
options.detached = true;
|
||||||
|
options.type = 4;
|
||||||
|
|
||||||
spawnDaemon(ret);
|
var child = require('child_process').execFile(process.execPath, options._parms, options);
|
||||||
|
if (!child) { throw ('Error spawning process'); }
|
||||||
return (ret);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user