pixl-boot 1.0.2 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -70
- package/boot.js +118 -34
- package/cli.js +0 -0
- package/package.json +4 -2
- package/.npmignore +0 -5
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Overview
|
|
2
2
|
|
|
3
|
-
`pixl-boot` will automatically register a startup service for your module on Linux and
|
|
3
|
+
`pixl-boot` will automatically register a startup service for your module on Linux and macOS, so your daemon will be started on a server reboot. It is configured entirely out of your [package.json](https://docs.npmjs.com/files/package.json) file, and will handle all the details of registering a [systemd service](https://en.wikipedia.org/wiki/Systemd) on Linux, or a [LaunchAgent/LaunchDaemon](https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html) on macOS.
|
|
4
4
|
|
|
5
5
|
This is only designed for packages that are installed as the root user.
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ First, add the `pixl-boot` package in the `dependencies` section of your `packag
|
|
|
10
10
|
|
|
11
11
|
```js
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"pixl-boot": "^
|
|
13
|
+
"pixl-boot": "^2.0.0"
|
|
14
14
|
}
|
|
15
15
|
```
|
|
16
16
|
|
|
@@ -22,18 +22,7 @@ Once you have your control script ready, link to it in the `bin` property in you
|
|
|
22
22
|
"bin": "bin/control.sh",
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
Finally, you need to have npm run `pixl-boot` on install and uninstall of your package, so that it has a chance to register and unregister your startup service. Do this by adding `
|
|
26
|
-
|
|
27
|
-
```js
|
|
28
|
-
"scripts": {
|
|
29
|
-
"postinstall": "pixl-boot install",
|
|
30
|
-
"preuninstall": "pixl-boot uninstall"
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
That's it!
|
|
35
|
-
|
|
36
|
-
Alternatively, if you would rather the startup service not be installed automatically, and instead require additional user commands, change the `scripts` property names to something custom, like `boot` and `unboot`:
|
|
25
|
+
Finally, you need to have npm run `pixl-boot` on install and uninstall of your package, so that it has a chance to register and unregister your startup service. Do this by adding `boot` and `unboot` properties in the `scripts` section of your `package.json` file:
|
|
37
26
|
|
|
38
27
|
```js
|
|
39
28
|
"scripts": {
|
|
@@ -42,9 +31,9 @@ Alternatively, if you would rather the startup service not be installed automati
|
|
|
42
31
|
}
|
|
43
32
|
```
|
|
44
33
|
|
|
45
|
-
Then your users
|
|
34
|
+
Then your users need to be instructed to type:
|
|
46
35
|
|
|
47
|
-
```
|
|
36
|
+
```sh
|
|
48
37
|
npm run boot
|
|
49
38
|
npm run unboot
|
|
50
39
|
```
|
|
@@ -61,8 +50,8 @@ Add `--name` if you want to customize the startup service name. This defaults t
|
|
|
61
50
|
|
|
62
51
|
```js
|
|
63
52
|
"scripts": {
|
|
64
|
-
"
|
|
65
|
-
"
|
|
53
|
+
"boot": "pixl-boot install --name mycustomservice",
|
|
54
|
+
"unboot": "pixl-boot uninstall --name mycustomservice"
|
|
66
55
|
}
|
|
67
56
|
```
|
|
68
57
|
|
|
@@ -72,8 +61,8 @@ Add `--company` if you want to customize the "company" (organization) name that
|
|
|
72
61
|
|
|
73
62
|
```js
|
|
74
63
|
"scripts": {
|
|
75
|
-
"
|
|
76
|
-
"
|
|
64
|
+
"boot": "pixl-boot install --company MyCompany",
|
|
65
|
+
"unboot": "pixl-boot uninstall --company MyCompany"
|
|
77
66
|
}
|
|
78
67
|
```
|
|
79
68
|
|
|
@@ -83,67 +72,37 @@ Add `--script` to specify a custom location of your shell control script, relati
|
|
|
83
72
|
|
|
84
73
|
```js
|
|
85
74
|
"scripts": {
|
|
86
|
-
"
|
|
87
|
-
}
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### linux_runlevels
|
|
91
|
-
|
|
92
|
-
Add `--linux_runlevels` if you want to customize the [Linux init.d Runlevels](https://en.wikipedia.org/wiki/Runlevel#Linux) for when your service should actually start up. This defaults to `3,4,5` denoting that your service should start at Runlevels 3, 4 and 5. Obviously, this only has effect when installing on Linux operating systems. You only need to add this to the `pixl-boot install` command. Example:
|
|
93
|
-
|
|
94
|
-
```js
|
|
95
|
-
"scripts": {
|
|
96
|
-
"postinstall": "pixl-boot install --linux_runlevels 3,4,5"
|
|
97
|
-
}
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### redhat_start_priority
|
|
101
|
-
|
|
102
|
-
Add `--redhat_start_priority` if you want to customize the [Linux init.d start priority](http://www.tldp.org/HOWTO/HighQuality-Apps-HOWTO/boot.html), which is a number from `01` to `99`. This controls when your service should start up, in relation to all the other services on the machine. This is only used by RedHat (CentOS / Fedora) flavors of Linux, and defaults to `99` (i.e. only start after everything else has). You only need to add this to the `pixl-boot install` command. Example:
|
|
103
|
-
|
|
104
|
-
```js
|
|
105
|
-
"scripts": {
|
|
106
|
-
"postinstall": "pixl-boot install --redhat_start_priority 99"
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### redhat_stop_priority
|
|
111
|
-
|
|
112
|
-
Add `--redhat_stop_priority` if you want to customize the [Linux init.d stop priority](http://www.tldp.org/HOWTO/HighQuality-Apps-HOWTO/boot.html), which is a number from `01` to `99`. This controls when your service should shut down, in relation to all the other services on the machine. This is only used by RedHat (CentOS / Fedora) flavors of Linux, and defaults to `01` (i.e. stop first, before anything else). You only need to add this to the `pixl-boot install` command. Example:
|
|
113
|
-
|
|
114
|
-
```js
|
|
115
|
-
"scripts": {
|
|
116
|
-
"postinstall": "pixl-boot install --redhat_stop_priority 01"
|
|
75
|
+
"boot": "pixl-boot install --script bin/my-control-script.sh"
|
|
117
76
|
}
|
|
118
77
|
```
|
|
119
78
|
|
|
120
|
-
###
|
|
79
|
+
### linux_type
|
|
121
80
|
|
|
122
|
-
Add `--
|
|
81
|
+
Add `--linux_type` if you want to customize the Linux systemd service type. It should be one of `simple`, `forking`, `oneshot`, `dbus`, `notify`, or `idle`. It defaults to `forking`. Example:
|
|
123
82
|
|
|
124
83
|
```js
|
|
125
84
|
"scripts": {
|
|
126
|
-
"
|
|
85
|
+
"boot": "pixl-boot install --linux_type forking"
|
|
127
86
|
}
|
|
128
87
|
```
|
|
129
88
|
|
|
130
|
-
###
|
|
89
|
+
### linux_after
|
|
131
90
|
|
|
132
|
-
Add `--
|
|
91
|
+
Add `--linux_after` if you want to specify a service that we must start *after*. This defaults to `network.target`, denoting that the server should have basic networking started before trying to start our service. Example:
|
|
133
92
|
|
|
134
93
|
```js
|
|
135
94
|
"scripts": {
|
|
136
|
-
"
|
|
95
|
+
"boot": "pixl-boot install --linux_after network.target"
|
|
137
96
|
}
|
|
138
97
|
```
|
|
139
98
|
|
|
140
|
-
###
|
|
99
|
+
### linux_wanted_by
|
|
141
100
|
|
|
142
|
-
Add `--
|
|
101
|
+
Add `--linux_wanted_by` if you want to customize the `WantedBy` property in the systemd service file. This defaults to `multi-user.target`. Example:
|
|
143
102
|
|
|
144
103
|
```js
|
|
145
104
|
"scripts": {
|
|
146
|
-
"
|
|
105
|
+
"boot": "pixl-boot install --linux_wanted_by multi-user.target"
|
|
147
106
|
}
|
|
148
107
|
```
|
|
149
108
|
|
|
@@ -178,17 +137,14 @@ require('fs').writeFileSync( "logs/pid.txt", process.pid );
|
|
|
178
137
|
In addition to the command-line interface for `pixl-boot` there is also a JavaScript API you can use in your Node.js code, to install and/or uninstall startup services. To use this, first call `require('pixl-boot)` to load the module, and the returned object exposes `install()` and `uninstall()` functions. Both functions accept an options object, and a callback. The options object accepts all the named command-line arguments, sans the hyphens. Example use:
|
|
179
138
|
|
|
180
139
|
```js
|
|
181
|
-
|
|
182
|
-
|
|
140
|
+
const boot = require('pixl-boot');
|
|
141
|
+
let opts = {
|
|
183
142
|
name: "MyService",
|
|
184
143
|
company: "Node",
|
|
185
144
|
script: "bin/control.sh",
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
debian_requires: "local_fs remote_fs network syslog named",
|
|
190
|
-
debian_stoplevels: "0,1,6",
|
|
191
|
-
darwin_type: "agent"
|
|
145
|
+
linux_type: "forking",
|
|
146
|
+
linux_after: "network.target",
|
|
147
|
+
linux_wanted_by: "multi-user.target"
|
|
192
148
|
};
|
|
193
149
|
|
|
194
150
|
// install startup service
|
|
@@ -204,9 +160,9 @@ boot.uninstall(opts, function(err) {
|
|
|
204
160
|
|
|
205
161
|
# Licenses
|
|
206
162
|
|
|
207
|
-
The MIT License
|
|
163
|
+
**The MIT License**
|
|
208
164
|
|
|
209
|
-
Copyright (c) 2016 Joseph Huckaby.
|
|
165
|
+
Copyright (c) 2016 - 2024 Joseph Huckaby.
|
|
210
166
|
|
|
211
167
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
212
168
|
of this software and associated documentation files (the "Software"), to deal
|
package/boot.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// PixlBoot API
|
|
2
2
|
// Install service to run on server startup
|
|
3
3
|
// Works on Linux (RedHat / Ubuntu) and OS X
|
|
4
|
-
// Copyright (c) 2016 Joseph Huckaby and PixlCore.com
|
|
4
|
+
// Copyright (c) 2016 - 2019 Joseph Huckaby and PixlCore.com
|
|
5
|
+
// MIT License
|
|
5
6
|
|
|
6
7
|
var fs = require('fs');
|
|
7
8
|
var cp = require('child_process');
|
|
@@ -13,12 +14,17 @@ module.exports = {
|
|
|
13
14
|
company: "Node",
|
|
14
15
|
script: "bin/control.sh",
|
|
15
16
|
|
|
17
|
+
// systemd stuff (modern)
|
|
18
|
+
linux_type: "forking",
|
|
19
|
+
linux_after: "network.target",
|
|
20
|
+
linux_wanted_by: "multi-user.target",
|
|
21
|
+
|
|
22
|
+
// init.d stuff (legacy)
|
|
16
23
|
linux_runlevels: "3,4,5",
|
|
17
24
|
redhat_start_priority: "99",
|
|
18
25
|
redhat_stop_priority: "01",
|
|
19
26
|
debian_requires: "local_fs remote_fs network syslog named",
|
|
20
|
-
debian_stoplevels: "0,1,6"
|
|
21
|
-
darwin_type: "agent"
|
|
27
|
+
debian_stoplevels: "0,1,6"
|
|
22
28
|
},
|
|
23
29
|
|
|
24
30
|
install: function(args, callback) {
|
|
@@ -45,36 +51,87 @@ module.exports = {
|
|
|
45
51
|
},
|
|
46
52
|
|
|
47
53
|
install_linux: function(args, callback) {
|
|
48
|
-
// install linux init.d service
|
|
54
|
+
// install linux systemd or init.d service
|
|
49
55
|
// first determine if we're on RedHat (CentOS / Fedora) or Debian (Ubuntu)
|
|
50
56
|
var self = this;
|
|
51
57
|
|
|
52
58
|
args.service_name = args.name.toLowerCase().replace(/\W+/g, '');
|
|
53
|
-
args.service_file = "/etc/init.d/" + args.service_name;
|
|
54
59
|
|
|
55
|
-
cp.exec("which
|
|
60
|
+
cp.exec("which systemctl", function(err, stdout, stderr) {
|
|
56
61
|
if (err) {
|
|
57
|
-
//
|
|
58
|
-
cp.exec("which
|
|
62
|
+
// oops, try one of the legacy methods
|
|
63
|
+
cp.exec("which chkconfig", function(err, stdout, stderr) {
|
|
59
64
|
if (err) {
|
|
60
|
-
// not
|
|
61
|
-
|
|
65
|
+
// not redhat, but are we on debian?
|
|
66
|
+
cp.exec("which update-rc.d", function(err, stdout, stderr) {
|
|
67
|
+
if (err) {
|
|
68
|
+
// not a supported linux platform
|
|
69
|
+
callback( new Error("Unsupported platform: No systemctl, chkconfig nor update-rc.d found.") );
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// we're on legacy debian
|
|
73
|
+
self.install_linux_debian(args, callback);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
62
76
|
}
|
|
63
77
|
else {
|
|
64
|
-
// we're on
|
|
65
|
-
self.
|
|
78
|
+
// we're on legacy redhat
|
|
79
|
+
self.install_linux_redhat(args, callback);
|
|
66
80
|
}
|
|
67
81
|
});
|
|
82
|
+
return;
|
|
68
83
|
}
|
|
69
84
|
else {
|
|
70
|
-
//
|
|
71
|
-
self.
|
|
85
|
+
// proceed with modern linux systemd
|
|
86
|
+
self.install_linux_systemd(args, callback);
|
|
72
87
|
}
|
|
73
88
|
});
|
|
74
89
|
},
|
|
75
90
|
|
|
91
|
+
install_linux_systemd: function(args, callback) {
|
|
92
|
+
// install service on linux with systemd (systemctl)
|
|
93
|
+
args.service_file = "/etc/systemd/system/" + args.service_name + ".service";
|
|
94
|
+
var service_type = args.linux_type;
|
|
95
|
+
var unit_after = args.linux_after;
|
|
96
|
+
var wanted_by = args.linux_wanted_by;
|
|
97
|
+
|
|
98
|
+
var service_contents = [
|
|
99
|
+
"[Unit]",
|
|
100
|
+
"Description=" + args.company + " " + args.name,
|
|
101
|
+
"After=" + unit_after,
|
|
102
|
+
"",
|
|
103
|
+
"[Service]",
|
|
104
|
+
"Type=" + service_type,
|
|
105
|
+
"ExecStart=" + args.script + " start",
|
|
106
|
+
"ExecStop=" + args.script + " stop",
|
|
107
|
+
"",
|
|
108
|
+
"[Install]",
|
|
109
|
+
"WantedBy=" + wanted_by
|
|
110
|
+
].join("\n") + "\n";
|
|
111
|
+
|
|
112
|
+
// write init.d config file
|
|
113
|
+
fs.writeFile( args.service_file, service_contents, { mode: 0o644 }, function(err) {
|
|
114
|
+
if (err) return callback( new Error("Failed to write file: " + args.service_file + ": " + err.message) );
|
|
115
|
+
|
|
116
|
+
// reload systemd
|
|
117
|
+
cp.exec("systemctl daemon-reload", function(err, stdout, stderr) {
|
|
118
|
+
if (err) callback( new Error("Failed to activate service: " + args.service_name + ": " + err.message) );
|
|
119
|
+
|
|
120
|
+
// activate service
|
|
121
|
+
cp.exec("systemctl enable " + args.service_name + ".service", function(err, stdout, stderr) {
|
|
122
|
+
if (err) callback( new Error("Failed to activate service: " + args.service_name + ": " + err.message) );
|
|
123
|
+
|
|
124
|
+
// success
|
|
125
|
+
callback();
|
|
126
|
+
}); // cp.exec
|
|
127
|
+
}); // cp.exec
|
|
128
|
+
}); // fs.writeFile
|
|
129
|
+
},
|
|
130
|
+
|
|
76
131
|
install_linux_redhat: function(args, callback) {
|
|
77
132
|
// install service on redhat (chkconfig)
|
|
133
|
+
// (this is legacy, only used if systemd/systemctl is not on system)
|
|
134
|
+
args.service_file = "/etc/init.d/" + args.service_name;
|
|
78
135
|
var runlevels = args.linux_runlevels.toString().replace(/\D+/g, '');
|
|
79
136
|
var rh_start_priority = this.zeroPad(args.redhat_start_priority, 2);
|
|
80
137
|
var rh_stop_priority = this.zeroPad(args.redhat_stop_priority, 2);
|
|
@@ -106,6 +163,8 @@ module.exports = {
|
|
|
106
163
|
|
|
107
164
|
install_linux_debian: function(args, callback) {
|
|
108
165
|
// install service on debian (update-rc.d)
|
|
166
|
+
// (this is legacy, only used if systemd/systemctl is not on system)
|
|
167
|
+
args.service_file = "/etc/init.d/" + args.service_name;
|
|
109
168
|
var runlevels = args.linux_runlevels.toString().replace(/\D+/g, '').split('').join(" ");
|
|
110
169
|
var deb_stoplevels = args.debian_stoplevels.toString().replace(/\D+/g, '').split('').join(" ");
|
|
111
170
|
var deb_requires = args.debian_requires.split(/\W+/).map( function(req) { return '$' + req; } ).join(" ");
|
|
@@ -115,7 +174,7 @@ module.exports = {
|
|
|
115
174
|
"",
|
|
116
175
|
"### BEGIN INIT INFO",
|
|
117
176
|
"# Provides: " + args.service_name,
|
|
118
|
-
"# Required-Start: " +
|
|
177
|
+
"# Required-Start: " + deb_requires,
|
|
119
178
|
"# Required-Stop: " + deb_requires,
|
|
120
179
|
"# Default-Start: " + runlevels,
|
|
121
180
|
"# Default-Stop: " + deb_stoplevels,
|
|
@@ -132,10 +191,12 @@ module.exports = {
|
|
|
132
191
|
|
|
133
192
|
// activate service
|
|
134
193
|
cp.exec("update-rc.d " + args.service_name + " defaults", function(err, stdout, stderr) {
|
|
135
|
-
if (err)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
194
|
+
if (err) {
|
|
195
|
+
callback( new Error("Failed to activate service: " + args.service_name + ": " + err.message) );
|
|
196
|
+
} else {
|
|
197
|
+
// success
|
|
198
|
+
callback();
|
|
199
|
+
}
|
|
139
200
|
}); // cp.exec
|
|
140
201
|
}); // fs.writeFile
|
|
141
202
|
},
|
|
@@ -144,7 +205,15 @@ module.exports = {
|
|
|
144
205
|
// install service as Darwin (OS X) agent or daemon
|
|
145
206
|
args.service_name = args.name.toLowerCase().replace(/\W+/g, '');
|
|
146
207
|
args.company_name = args.company.toLowerCase().replace(/\W+/g, '');
|
|
147
|
-
|
|
208
|
+
|
|
209
|
+
if (process.getuid() == 0) {
|
|
210
|
+
// we're root, so install a LaunchDaemon
|
|
211
|
+
args.plist_file = "/Library/LaunchDaemons/com." + args.company_name + "." + args.service_name + ".plist";
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
// we're a standard user, so install a user-level LaunchAgent
|
|
215
|
+
args.plist_file = process.env.HOME + "/Library/LaunchAgents/com." + args.company_name + "." + args.service_name + ".plist";
|
|
216
|
+
}
|
|
148
217
|
|
|
149
218
|
var plist_contents = [
|
|
150
219
|
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
@@ -169,14 +238,7 @@ module.exports = {
|
|
|
169
238
|
// write plist config file
|
|
170
239
|
fs.writeFile( args.plist_file, plist_contents, { mode: '644' }, function(err) {
|
|
171
240
|
if (err) return callback( new Error("Failed to write file: " + args.plist_file + ": " + err.message) );
|
|
172
|
-
|
|
173
|
-
// must be root/wheel
|
|
174
|
-
cp.exec( "chown root:wheel " + args.plist_file, function(err) {
|
|
175
|
-
if (err) return callback( new Error("Failed to chmod plist file: " + args.plist_file + ": " + err.message) );
|
|
176
|
-
|
|
177
|
-
// success
|
|
178
|
-
callback();
|
|
179
|
-
});
|
|
241
|
+
callback();
|
|
180
242
|
});
|
|
181
243
|
},
|
|
182
244
|
|
|
@@ -192,19 +254,41 @@ module.exports = {
|
|
|
192
254
|
|
|
193
255
|
args.service_name = args.name.toLowerCase().replace(/\W+/g, '');
|
|
194
256
|
args.company_name = args.company.toLowerCase().replace(/\W+/g, '');
|
|
195
|
-
args.service_file = "/etc/init.d/" + args.service_name;
|
|
196
257
|
|
|
197
258
|
if (process.platform == 'linux') {
|
|
198
|
-
//
|
|
199
|
-
|
|
200
|
-
|
|
259
|
+
// try every which way to remove service
|
|
260
|
+
args.service_file = "/etc/systemd/system/" + args.service_name + ".service";
|
|
261
|
+
|
|
262
|
+
fs.access( args.service_file, function(err) {
|
|
263
|
+
if (err) {
|
|
264
|
+
// nope, try legacy methods
|
|
265
|
+
args.service_file = "/etc/init.d/" + args.service_name;
|
|
266
|
+
|
|
267
|
+
// chkconfig may or may not work, so ignore error
|
|
268
|
+
cp.exec( "chkconfig " + args.service_name + " off", function() {
|
|
269
|
+
cp.exec( "rm -f /etc/rc*.d/*" + args.service_name, function() {
|
|
270
|
+
fs.unlink( args.service_file, callback );
|
|
271
|
+
} );
|
|
272
|
+
} );
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// looks like we have a systemd service
|
|
277
|
+
cp.exec( "systemctl disable " + args.service_name + ".service", function() {
|
|
201
278
|
fs.unlink( args.service_file, callback );
|
|
202
279
|
} );
|
|
203
|
-
}
|
|
280
|
+
}); // fs.access
|
|
204
281
|
}
|
|
205
282
|
else {
|
|
206
283
|
// non-linux (darwin)
|
|
207
|
-
|
|
284
|
+
if (process.getuid() == 0) {
|
|
285
|
+
// we're root, so uninstall the LaunchDaemon
|
|
286
|
+
args.plist_file = "/Library/LaunchDaemons/com." + args.company_name + "." + args.service_name + ".plist";
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
// we're a standard user, so uninstall the user-level LaunchAgent
|
|
290
|
+
args.plist_file = process.env.HOME + "/Library/LaunchAgents/com." + args.company_name + "." + args.service_name + ".plist";
|
|
291
|
+
}
|
|
208
292
|
|
|
209
293
|
fs.unlink( args.plist_file, callback );
|
|
210
294
|
}
|
package/cli.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pixl-boot",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Register your service to launch on server startup (Linux / OS X).",
|
|
5
5
|
"author": "Joseph Huckaby <jhuckaby@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/jhuckaby/pixl-boot",
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
"linux",
|
|
23
23
|
"darwin",
|
|
24
24
|
"init.d",
|
|
25
|
-
"launchd"
|
|
25
|
+
"launchd",
|
|
26
|
+
"systemd",
|
|
27
|
+
"systemctl"
|
|
26
28
|
],
|
|
27
29
|
"dependencies": {
|
|
28
30
|
"pixl-cli": "^1.0.0"
|