diff --git a/README.md b/README.md index aee8f6e..a6e287a 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ var svc = new Service({ ] //, workingDirectory: '...' //, allowServiceLogon: true + //, autoServiceRestart: true }); // Listen for the "install" event, which indicates the @@ -257,6 +258,18 @@ var svc = new Service({ dependsOn: ["serviceA"] }); ``` +### Handle service level process death + +The service can also be restarted by windows in the event that the underlying wrapper process dies. + +```js +var svc = new Service({ + name:'Hello World', + description: 'The nodejs.org example web server.', + script: 'C:\\path\\to\\helloworld.js', + autoServiceRestart: true +}); +``` ### Cleaning Up: Uninstall a Service diff --git a/example/install.js b/example/install.js index 34566a1..6d5f1ad 100644 --- a/example/install.js +++ b/example/install.js @@ -10,7 +10,8 @@ var svc = new Service({ env:{ name: "NODE_ENV", value: "production" - } + }, + autoServiceRestart: false }); // Listen for the "install" event, which indicates the diff --git a/example/package-lock.json b/example/package-lock.json new file mode 100644 index 0000000..bd91ab7 --- /dev/null +++ b/example/package-lock.json @@ -0,0 +1,205 @@ +{ + "name": "example", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "node-windows": "^1.0.0-beta.8" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-windows": { + "version": "1.0.0-beta.8", + "resolved": "https://registry.npmjs.org/node-windows/-/node-windows-1.0.0-beta.8.tgz", + "integrity": "sha512-uLekXnSeem3nW5escID224Fd0U/1VtvE796JpSpOY+c73Cslz/Qn2WUHRJyPQJEMrNGAy/FMRFjjhh4z1alZTA==", + "license": "MIT", + "dependencies": { + "xml": "1.0.1", + "yargs": "^17.5.1" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", + "license": "MIT" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/example/package.json b/example/package.json index d9335fb..e917195 100644 --- a/example/package.json +++ b/example/package.json @@ -1,5 +1,5 @@ { "dependencies": { - "node-windows": "^1.0.0-beta.7" + "node-windows": "^1.0.0-beta.8" } } diff --git a/lib/daemon.js b/lib/daemon.js index 302d1b6..c862fb6 100644 --- a/lib/daemon.js +++ b/lib/daemon.js @@ -130,6 +130,7 @@ var daemon = function (config) { workingdirectory: this.workingdirectory, stopparentfirst: this.stopparentfirst, stoptimeout: this.stoptimeout, + autoServiceRestart: this.autoServiceRestart, logmode: this.logmode, logging: config.logging, allowServiceLogon: config.allowServiceLogon, @@ -339,6 +340,14 @@ var daemon = function (config) { value: config.description || '' }, + // setup as a restarting node service + autoServiceRestart: { + enumerable: true, + writable: false, + configurable: false, + value: config.autoServiceRestart || false + }, + /** * @property {Object} [user] * If you need to specify a specific user or particular credentials to manage a service, the following diff --git a/lib/winsw.js b/lib/winsw.js index 03b5a85..b7612a2 100644 --- a/lib/winsw.js +++ b/lib/winsw.js @@ -143,6 +143,11 @@ console.log({loc: 'winsw.js ~line 77', xml, config}) } } + if(config.autoServiceRestart) { + // add + xml.push({onfailure: [{ _attr: { action: 'restart', delay: '10 sec' }}]}); + } + // if no working directory specified, use current working directory // that this process was launched with xml.push({workingdirectory: config.workingdirectory || process.cwd()}); diff --git a/lib/wrapper.js b/lib/wrapper.js index 019958b..a9dc5f4 100644 --- a/lib/wrapper.js +++ b/lib/wrapper.js @@ -99,13 +99,8 @@ if (typeof argv.m === 'string') { // Set the absolute path of the file argv.f = p.resolve(argv.f); -// Hack to force the wrapper process to stay open by launching a ghost socket server -var server = net.createServer().listen(); - -server.on('error', function (err) { - launch('warn', err.message); - server = net.createServer().listen(); -}); +// Force the wrapper process to stay open by creating a heartbeat +setInterval(() => {}, 86400000); /** * @method monitor @@ -212,7 +207,9 @@ process.on("SIGINT", killkid); process.on("SIGTERM", killkid); process.on('uncaughtException', function (err) { - launch('warn', err.message); + console.log('node-windows Wrapper service: process uncaught exception:'); + console.log(err); + process.exit(1); }); // Launch the process diff --git a/package-lock.json b/package-lock.json index b83ac4d..e3543eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "node-windows", - "version": "1.0.0-beta.8", + "version": "1.0.0-beta.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "node-windows", - "version": "1.0.0-beta.8", + "version": "1.0.0-beta.9", "license": "MIT", "dependencies": { "xml": "1.0.1", diff --git a/package.json b/package.json index 9301f17..a6193ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-windows", - "version": "1.0.0-beta.8", + "version": "1.0.0-beta.9", "description": "Support for Windows services, event logging, UAC, and several helper methods for interacting with the OS.", "keywords": [ "ngn",