unitup 0.0.9 â 0.0.10
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 +395 -180
- package/docs/index.html +531 -0
- package/index.d.ts +133 -152
- package/package.json +4 -1
- package/src/cli.js +254 -53
- package/src/doctor.js +73 -14
- package/src/index.js +16 -1
- package/src/runtimes/bun.js +46 -0
- package/src/runtimes/common.js +73 -0
- package/src/runtimes/deno.js +46 -0
- package/src/runtimes/elixir.js +46 -0
- package/src/runtimes/go.js +46 -0
- package/src/runtimes/index.js +155 -0
- package/src/runtimes/native.js +38 -0
- package/src/runtimes/node.js +57 -0
- package/src/runtimes/php.js +46 -0
- package/src/runtimes/python.js +46 -0
- package/src/runtimes/ruby.js +46 -0
- package/src/runtimes/shell.js +46 -0
- package/src/systemd.js +221 -28
- package/src/unit.js +59 -21
- package/src/utils.js +139 -4
package/README.md
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
# unitup
|
|
2
2
|
|
|
3
|
-
> Minimal, zero-dependency
|
|
3
|
+
> Minimal, zero-dependency CLI & library to run Node.js, Python, Ruby, PHP, Bun, Deno, Go, Elixir, Shell scripts, and native binaries as `systemd` user services.
|
|
4
4
|
|
|
5
5
|
`unitup` provides a thin, user-level layer over Linux `systemd`. It does **not** create a custom daemon, manage process trees, or act as a PM2 alternative. Instead, it generates and manages native systemd user units (`~/.config/systemd/user/unitup-<name>.service`), letting systemd handle process supervision, auto-restarts, logging, and OS boot startup without requiring `sudo` privileges.
|
|
6
6
|
|
|
7
|
+
```bash
|
|
8
|
+
# Quick Start
|
|
9
|
+
npm install -g unitup
|
|
10
|
+
|
|
11
|
+
unitup add server.js --start
|
|
12
|
+
unitup status server
|
|
13
|
+
unitup logs server --follow
|
|
14
|
+
|
|
15
|
+
# Multi-runtime & Native Executables
|
|
16
|
+
unitup add worker.py --runtime python --start
|
|
17
|
+
unitup add ./server --runtime native --name api --start
|
|
18
|
+
```
|
|
19
|
+
|
|
7
20
|
---
|
|
8
21
|
|
|
9
|
-
##
|
|
22
|
+
## unitup vs PM2
|
|
10
23
|
|
|
11
24
|
`unitup` is **not** a PM2 replacement or an independent process manager. While PM2 runs its own master daemon, `unitup` is strictly a thin and transparent CLI layer on top of Linux `systemd`.
|
|
12
25
|
|
|
@@ -14,39 +27,109 @@
|
|
|
14
27
|
|
|
15
28
|
| Feature | `unitup` | PM2 |
|
|
16
29
|
| :--- | :--- | :--- |
|
|
17
|
-
| **Background Process (Daemon)** | **
|
|
30
|
+
| **Background Process (Daemon)** | **No resident unitup daemon**. Systemd directly supervises processes. | **Runs a persistent process-management daemon**. |
|
|
18
31
|
| **System Integration** | Native Linux OS `systemd` user service (`~/.config/systemd/user/`). | Custom process monitoring via PM2's internal daemon. |
|
|
19
|
-
| **
|
|
32
|
+
| **Multi-Runtime & Executable Support** | **Node.js, Python, Ruby, PHP, Bun, Deno, Go, Elixir, Shell, and native binaries** out of the box. | **Node.js-focused process manager with support for running other commands**. |
|
|
33
|
+
| **Privileges Required** | Does **not** require `sudo`. | Boot integration commonly requires running the PM2 startup setup command with elevated privileges. |
|
|
20
34
|
| **Dependencies** | **0 Runtime Dependencies** (Uses Node.js standard modules only). | Dozens of 3rd party npm packages. |
|
|
21
35
|
| **Log Management** | Delegates to native Linux `journald` system (`journalctl`). | Manages `.pm2/logs` files (requires `pm2-logrotate` for rotation). |
|
|
22
36
|
| **Boot Startup** | Native systemd lingering (`loginctl enable-linger`). | Custom startup script launching PM2 daemon. |
|
|
23
37
|
|
|
24
38
|
---
|
|
25
39
|
|
|
26
|
-
###
|
|
40
|
+
### Core Architecture
|
|
41
|
+
|
|
42
|
+
At its core, `unitup` generates systemd service unit files directly from a generic `command + args` model rather than being hardcoded to Node.js:
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
{
|
|
46
|
+
command: "/usr/bin/python3",
|
|
47
|
+
args: ["/home/user/apps/worker.py"],
|
|
48
|
+
cwd: "/home/user/apps",
|
|
49
|
+
env: {
|
|
50
|
+
APP_ENV: "production"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Core Promises
|
|
27
56
|
|
|
28
|
-
1. ⥠**
|
|
29
|
-
2.
|
|
30
|
-
3.
|
|
31
|
-
4.
|
|
57
|
+
1. ⥠**No persistent unitup CPU or memory overhead**: After running `unitup` commands, `unitup` exits immediately. No extra master process stays running in the background.
|
|
58
|
+
2. ð **Language-Agnostic & Executable Ready**: Works out of the box with Node.js, Python, Ruby, PHP, Bun, Deno, Go, Elixir, Shell scripts, or compiled native binaries.
|
|
59
|
+
3. ð **Transparent systemd-native configuration**: Avoids shell execution and validates generated unit arguments (`shell: false`). Generated `.service` files are saved as standard text at `~/.config/systemd/user/`.
|
|
60
|
+
4. ð ïļ **Automatic Absolute Path & PATH Resolution**: Resolves absolute binary and script paths, automatically injecting proper `PATH` environment into unit files.
|
|
61
|
+
5. ð **Backward Compatible**: Full support for existing Node.js projects, legacy CLI parameters, and old metadata formats (`{ node, script }`).
|
|
32
62
|
|
|
33
|
-
|
|
63
|
+
---
|
|
34
64
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
65
|
+
## Supported Runtimes
|
|
66
|
+
|
|
67
|
+
- **Node.js**: `.js`, `.mjs`, `.cjs`
|
|
68
|
+
- **Python**: `.py` (resolves `python3` then `python`)
|
|
69
|
+
- **Ruby**: `.rb` (`ruby`)
|
|
70
|
+
- **PHP**: `.php` (`php`)
|
|
71
|
+
- **Bun**: `bun`
|
|
72
|
+
- **Deno**: `deno` (default command: `deno run <script>`)
|
|
73
|
+
- **Go**: `.go` (`go run <script>`)
|
|
74
|
+
- **Elixir**: `.ex`, `.exs` (`elixir <script>`)
|
|
75
|
+
- **Shell Scripts**: `.sh` (`bash`, `sh`)
|
|
76
|
+
- **Native Executables**: `./server` (compiled Go, Rust, C/C++, etc.)
|
|
39
77
|
|
|
40
78
|
---
|
|
41
79
|
|
|
42
80
|
## Features
|
|
43
81
|
|
|
44
|
-
- ⥠**Zero runtime dependencies** â
|
|
45
|
-
- ð **No
|
|
46
|
-
- ðĄïļ **Secure by design** â
|
|
47
|
-
-
|
|
82
|
+
- ⥠**Zero runtime dependencies** â lightweight, ESM-first package with CommonJS support.
|
|
83
|
+
- ð **No sudo required for normal service creation and management** â operates entirely within systemd user scope (`~/.config/systemd/user/`).
|
|
84
|
+
- ðĄïļ **Secure by design** â avoids shell-based command execution, validates service names, escapes systemd arguments, and sanitizes input to prevent shell injection.
|
|
85
|
+
- ð§ **Systemd-Native Memory Limits** â Configure `MemoryHigh`, `MemoryMax`, and `MemorySwapMax` per service without extra monitoring daemons.
|
|
86
|
+
- ð **Journald Log Maintenance** â Advanced log streaming with filters (`--since`, `--until`, `--priority`, `--grep`, `--boot`, `--json`) and journal maintenance (`disk-usage`, `rotate`, `vacuum`).
|
|
87
|
+
- ðĐš **System readiness & runtime check** â `unitup doctor` verifies OS, systemd PID 1, systemctl user bus, cgroup v2 memory controller support, user lingering, and detected runtimes.
|
|
48
88
|
- ð **Compact status & logs** â clean summary output from `systemctl show` and live `journalctl` streaming.
|
|
49
|
-
- ðĶ **Programmatic API** â imported directly into JavaScript applications.
|
|
89
|
+
- ðĶ **Programmatic API** â imported directly into JavaScript and TypeScript applications.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## CLI Usage
|
|
94
|
+
|
|
95
|
+
### Memory Limits
|
|
96
|
+
|
|
97
|
+
`unitup` allows you to set native systemd memory limits for your services without running background monitoring daemons:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Add a service with memory limits
|
|
101
|
+
unitup add server.js \
|
|
102
|
+
--memory-high 400M \
|
|
103
|
+
--memory-max 512M \
|
|
104
|
+
--swap-max 256M
|
|
105
|
+
|
|
106
|
+
# Update limits on an existing service
|
|
107
|
+
unitup limits api --memory-high 400M --memory-max 512M
|
|
108
|
+
|
|
109
|
+
# Reset memory limits back to system defaults
|
|
110
|
+
unitup limits api --reset-memory
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
*Supported size units:* `128K`, `256M`, `1G`, `infinity`, `max`, or raw byte integers.
|
|
114
|
+
|
|
115
|
+
### Journald Log Maintenance
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# Filter logs by time, priority, grep keyword, boot, or JSON output
|
|
119
|
+
unitup logs api --since 1h --until now
|
|
120
|
+
unitup logs api --priority err --grep "timeout"
|
|
121
|
+
unitup logs api --boot --json
|
|
122
|
+
|
|
123
|
+
# Journal storage maintenance
|
|
124
|
+
unitup journal disk-usage
|
|
125
|
+
unitup journal rotate
|
|
126
|
+
unitup journal vacuum --size 500M
|
|
127
|
+
unitup journal vacuum --time 14d
|
|
128
|
+
unitup journal vacuum --files 10 --yes
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
> [!NOTE]
|
|
132
|
+
> `unitup journal vacuum` prompts for user confirmation before executing system-wide log cleanup unless `--yes` / `-y` or `--dry-run` is provided. If permissions are insufficient, `unitup` handles it gracefully without executing `sudo`.
|
|
50
133
|
|
|
51
134
|
---
|
|
52
135
|
|
|
@@ -72,155 +155,195 @@ npm install unitup
|
|
|
72
155
|
|
|
73
156
|
---
|
|
74
157
|
|
|
75
|
-
##
|
|
158
|
+
## CLI Usage
|
|
159
|
+
|
|
160
|
+
### Multi-Runtime Examples
|
|
76
161
|
|
|
77
162
|
```bash
|
|
78
|
-
#
|
|
79
|
-
unitup
|
|
163
|
+
# Node.js
|
|
164
|
+
unitup add server.js --runtime node
|
|
80
165
|
|
|
81
|
-
#
|
|
82
|
-
unitup add
|
|
83
|
-
unitup add worker.js --name worker --group myproject --start
|
|
166
|
+
# Python
|
|
167
|
+
unitup add worker.py --runtime python
|
|
84
168
|
|
|
85
|
-
#
|
|
86
|
-
unitup
|
|
87
|
-
# or alias
|
|
88
|
-
unitup ls --group myproject
|
|
169
|
+
# Ruby
|
|
170
|
+
unitup add app.rb --runtime ruby
|
|
89
171
|
|
|
90
|
-
#
|
|
91
|
-
unitup
|
|
92
|
-
unitup stop @myproject
|
|
172
|
+
# PHP (with runtime flags)
|
|
173
|
+
unitup add index.php --runtime php --runtime-arg -S --runtime-arg 0.0.0.0:8080
|
|
93
174
|
|
|
94
|
-
#
|
|
95
|
-
unitup
|
|
175
|
+
# Bun
|
|
176
|
+
unitup add server.ts --runtime bun
|
|
96
177
|
|
|
97
|
-
#
|
|
98
|
-
unitup
|
|
178
|
+
# Deno (with runtime permission flags)
|
|
179
|
+
unitup add server.ts --runtime deno --runtime-arg --allow-net --runtime-arg --allow-env
|
|
180
|
+
|
|
181
|
+
# Go
|
|
182
|
+
unitup add main.go --runtime go
|
|
183
|
+
|
|
184
|
+
# Elixir
|
|
185
|
+
unitup add app.exs --runtime elixir
|
|
99
186
|
|
|
100
|
-
#
|
|
101
|
-
unitup
|
|
187
|
+
# Native Executable
|
|
188
|
+
unitup add ./server --runtime native --name api
|
|
102
189
|
|
|
103
|
-
#
|
|
104
|
-
unitup
|
|
190
|
+
# Generic Command Line Usage (bypasses runtime detection)
|
|
191
|
+
unitup add \
|
|
192
|
+
--name worker \
|
|
193
|
+
--command /usr/bin/python3 \
|
|
194
|
+
--arg /home/user/apps/worker.py \
|
|
195
|
+
--arg --port \
|
|
196
|
+
--arg 3000
|
|
105
197
|
```
|
|
106
198
|
|
|
199
|
+
> *Note: For production deployments, compiling the Go application and registering the resulting native binary is recommended.*
|
|
200
|
+
|
|
107
201
|
---
|
|
108
202
|
|
|
109
|
-
##
|
|
203
|
+
## Automatic Runtime & Shebang Detection
|
|
110
204
|
|
|
111
|
-
|
|
205
|
+
`unitup` automatically detects the runtime based on file extension and shebang headers:
|
|
112
206
|
|
|
113
|
-
Performs comprehensive system and Node.js runtime diagnostic checks:
|
|
114
|
-
- OS check (Linux)
|
|
115
|
-
- `systemctl` executable availability
|
|
116
|
-
- PID 1 systemd verification
|
|
117
|
-
- Systemd user bus accessibility
|
|
118
|
-
- Node.js executable PATH resolution (`which node`, `command -v`, `process.execPath`)
|
|
119
|
-
- Node.js binary execution capability (`node -v`)
|
|
120
|
-
- Unit directory write permissions (`~/.config/systemd/user/`)
|
|
121
|
-
- User lingering state (`loginctl enable-linger`)
|
|
122
|
-
|
|
123
|
-
Example output:
|
|
124
207
|
```text
|
|
125
|
-
|
|
208
|
+
.js, .mjs, .cjs â node
|
|
209
|
+
.py â python
|
|
210
|
+
.rb â ruby
|
|
211
|
+
.php â php
|
|
212
|
+
.sh â shell
|
|
213
|
+
.go â go
|
|
214
|
+
.ex, .exs â elixir
|
|
215
|
+
```
|
|
126
216
|
|
|
127
|
-
|
|
128
|
-
â systemctl available
|
|
129
|
-
â systemd is running
|
|
130
|
-
â systemd user services available
|
|
131
|
-
â Node.js: /usr/bin/node
|
|
132
|
-
â Node version: v20.11.0
|
|
133
|
-
â PATH includes node
|
|
134
|
-
! User lingering is disabled
|
|
217
|
+
Shebang examples detected automatically:
|
|
135
218
|
|
|
136
|
-
|
|
137
|
-
|
|
219
|
+
```text
|
|
220
|
+
#!/usr/bin/env python3
|
|
221
|
+
#!/usr/bin/env node
|
|
222
|
+
#!/usr/bin/env ruby
|
|
223
|
+
#!/bin/bash
|
|
224
|
+
```
|
|
138
225
|
|
|
139
|
-
|
|
140
|
-
|
|
226
|
+
For ambiguous extensions such as `.ts`, `unitup` requires explicit runtime selection:
|
|
227
|
+
|
|
228
|
+
```text
|
|
229
|
+
Could not determine runtime for server.ts.
|
|
230
|
+
|
|
231
|
+
Specify one:
|
|
232
|
+
unitup add server.ts --runtime bun
|
|
233
|
+
unitup add server.ts --runtime deno
|
|
234
|
+
unitup add server.ts --runtime node
|
|
141
235
|
```
|
|
142
236
|
|
|
143
237
|
---
|
|
144
238
|
|
|
145
|
-
|
|
239
|
+
## Native Executable Support
|
|
146
240
|
|
|
147
|
-
|
|
241
|
+
When adding a native executable:
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
unitup add ./server --runtime native --name api
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
`unitup` checks that the file:
|
|
248
|
+
1. Exists
|
|
249
|
+
2. Is a regular file
|
|
250
|
+
3. Has execute permission (`chmod +x`)
|
|
251
|
+
|
|
252
|
+
If execute permission is missing, `unitup` does **not** modify permissions automatically; it provides a helpful command suggestion:
|
|
148
253
|
|
|
149
|
-
#### 1. Node.js not found in PATH
|
|
150
254
|
```text
|
|
151
|
-
|
|
255
|
+
The executable is not runnable.
|
|
152
256
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
or via package manager:
|
|
156
|
-
sudo apt install nodejs
|
|
257
|
+
Run:
|
|
258
|
+
chmod +x /home/user/apps/server
|
|
157
259
|
```
|
|
158
260
|
|
|
159
|
-
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## CLI Commands Reference
|
|
264
|
+
|
|
265
|
+
### `unitup doctor`
|
|
266
|
+
|
|
267
|
+
Performs comprehensive system readiness and runtime diagnostic checks:
|
|
268
|
+
|
|
160
269
|
```text
|
|
161
|
-
|
|
270
|
+
unitup doctor
|
|
162
271
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
272
|
+
â Linux detected
|
|
273
|
+
â systemctl available
|
|
274
|
+
â systemd is running
|
|
275
|
+
â systemd user services available
|
|
166
276
|
|
|
167
|
-
|
|
168
|
-
|
|
277
|
+
Detected runtimes:
|
|
278
|
+
â Node.js: /usr/bin/node
|
|
279
|
+
â Python: /usr/bin/python3
|
|
280
|
+
â Ruby: /usr/bin/ruby
|
|
281
|
+
â Go: /usr/local/go/bin/go
|
|
282
|
+
- Bun: not found
|
|
283
|
+
- Deno: not found
|
|
284
|
+
- Elixir: not found
|
|
285
|
+
|
|
286
|
+
â Unit directory writable
|
|
287
|
+
! User lingering is disabled
|
|
169
288
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
Type=simple
|
|
173
|
-
WorkingDirectory=/home/user/projects/app
|
|
174
|
-
Environment=PATH="/home/user/.nvm/versions/node/v20.11.0/bin:/usr/local/bin:/usr/bin:/bin"
|
|
175
|
-
ExecStart=/home/user/.nvm/versions/node/v20.11.0/bin/node /home/user/projects/app/server.js
|
|
289
|
+
Enable it manually:
|
|
290
|
+
loginctl enable-linger username
|
|
176
291
|
```
|
|
177
292
|
|
|
178
|
-
|
|
293
|
+
*Note: Missing optional runtimes do not cause `unitup doctor` to exit with an error.*
|
|
179
294
|
|
|
180
|
-
|
|
181
|
-
unitup add app.js --node /usr/bin/node
|
|
182
|
-
```
|
|
295
|
+
---
|
|
183
296
|
|
|
184
|
-
|
|
297
|
+
### Missing Runtime Handling
|
|
298
|
+
|
|
299
|
+
If a requested runtime is not installed on the system, `unitup` provides clear installation guidance:
|
|
300
|
+
|
|
301
|
+
```text
|
|
302
|
+
Python runtime could not be found.
|
|
303
|
+
|
|
304
|
+
Install Python or specify its path:
|
|
305
|
+
unitup add worker.py --command /usr/bin/python3
|
|
306
|
+
```
|
|
185
307
|
|
|
186
308
|
---
|
|
187
309
|
|
|
188
|
-
### `unitup add
|
|
310
|
+
### `unitup add`
|
|
189
311
|
|
|
190
312
|
Creates a new systemd user service unit file at `~/.config/systemd/user/unitup-<name>.service`.
|
|
191
313
|
|
|
192
314
|
```bash
|
|
193
|
-
unitup add
|
|
194
|
-
unitup add server.js --name api --env NODE_ENV=production --env PORT=3000 --start
|
|
315
|
+
unitup add worker.py --name worker --group backend --start
|
|
195
316
|
```
|
|
196
317
|
|
|
197
318
|
**Options:**
|
|
198
319
|
- `--name <name>`: Custom service name (defaults to script file name without extension).
|
|
199
|
-
- `--
|
|
320
|
+
- `--runtime <name>`: Specify runtime (`node`, `python`, `ruby`, `php`, `bun`, `deno`, `shell`, `go`, `elixir`, `native`).
|
|
321
|
+
- `--runtime-arg <val>`: Pass flag/argument to runtime binary (can be specified multiple times).
|
|
322
|
+
- `--command <path>`: Explicit binary executable path (bypasses auto-detection).
|
|
323
|
+
- `--arg <value>`: Script/command argument (can be specified multiple times).
|
|
324
|
+
- `--group <group>`: Assign service to a group (default: `default`).
|
|
200
325
|
- `--cwd <path>`: Working directory (defaults to script directory).
|
|
201
326
|
- `--env KEY=value`: Pass environment variable (can be specified multiple times).
|
|
202
|
-
- `--env-file <file>`:
|
|
203
|
-
- `--restart <policy>`: Systemd restart policy (`on-failure`, `always`, `no`, `on-abnormal
|
|
204
|
-
- `--arg <value>`: Script positional arguments (can be specified multiple times).
|
|
327
|
+
- `--env-file <file>`: Path to environment file (adds `EnvironmentFile=...`).
|
|
328
|
+
- `--restart <policy>`: Systemd restart policy (`on-failure`, `always`, `no`, `on-abnormal`. Default: `on-failure`).
|
|
205
329
|
- `--start`: Automatically enables and starts the service immediately (`systemctl --user enable --now`).
|
|
206
330
|
|
|
207
|
-
Generated unit file example (`~/.config/systemd/user/unitup-
|
|
331
|
+
Generated unit file example (`~/.config/systemd/user/unitup-worker.service`):
|
|
208
332
|
|
|
209
333
|
```ini
|
|
210
334
|
[Unit]
|
|
211
|
-
Description=unitup service:
|
|
335
|
+
Description=unitup service: worker
|
|
212
336
|
After=network.target
|
|
213
337
|
|
|
214
338
|
[Service]
|
|
215
339
|
Type=simple
|
|
216
|
-
|
|
217
|
-
|
|
340
|
+
SyslogIdentifier=unitup-worker
|
|
341
|
+
WorkingDirectory=/home/user/apps
|
|
342
|
+
ExecStart=/usr/bin/python3 /home/user/apps/worker.py
|
|
218
343
|
Restart=on-failure
|
|
219
344
|
RestartSec=3
|
|
220
|
-
EnvironmentFile=/home/user/projects/app/.env
|
|
221
345
|
Environment=PATH="/usr/bin:/usr/local/bin:/bin"
|
|
222
|
-
Environment=
|
|
223
|
-
Environment=PORT="3000"
|
|
346
|
+
Environment=APP_ENV="production"
|
|
224
347
|
|
|
225
348
|
[Install]
|
|
226
349
|
WantedBy=default.target
|
|
@@ -228,138 +351,188 @@ WantedBy=default.target
|
|
|
228
351
|
|
|
229
352
|
---
|
|
230
353
|
|
|
231
|
-
### `unitup
|
|
354
|
+
### `unitup list` / `unitup ls`
|
|
232
355
|
|
|
233
|
-
|
|
356
|
+
Lists all user services managed by `unitup`:
|
|
234
357
|
|
|
235
358
|
```bash
|
|
236
|
-
unitup
|
|
359
|
+
unitup list
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
```text
|
|
363
|
+
NAME RUNTIME STATUS PID COMMAND
|
|
364
|
+
api node running 14220 node server.js
|
|
365
|
+
worker python running 14302 python3 worker.py
|
|
366
|
+
server native stopped - ./server
|
|
237
367
|
```
|
|
238
368
|
|
|
239
|
-
|
|
369
|
+
Filter by group:
|
|
370
|
+
|
|
371
|
+
```bash
|
|
372
|
+
unitup list --group backend
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
### `unitup inspect <name>`
|
|
378
|
+
|
|
379
|
+
View detailed configuration and status overview for a service (without revealing secrets or environment variables):
|
|
380
|
+
|
|
381
|
+
```bash
|
|
382
|
+
unitup inspect worker
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
```text
|
|
386
|
+
Name: worker
|
|
387
|
+
Runtime: python
|
|
388
|
+
Group: backend
|
|
389
|
+
Status: running
|
|
390
|
+
Command: /usr/bin/python3
|
|
391
|
+
Arguments: /home/user/apps/worker.py
|
|
392
|
+
Working directory: /home/user/apps
|
|
393
|
+
Unit: unitup-worker.service
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
### `unitup start <name|@group>`
|
|
399
|
+
|
|
400
|
+
Starts a service or an entire group:
|
|
240
401
|
|
|
241
402
|
```bash
|
|
242
|
-
unitup start
|
|
403
|
+
unitup start worker
|
|
404
|
+
unitup start @backend --enable
|
|
243
405
|
```
|
|
244
406
|
|
|
245
407
|
---
|
|
246
408
|
|
|
247
|
-
### `unitup stop <name>`
|
|
409
|
+
### `unitup stop <name|@group>`
|
|
248
410
|
|
|
249
|
-
Stops a
|
|
411
|
+
Stops a service or an entire group:
|
|
250
412
|
|
|
251
413
|
```bash
|
|
252
|
-
unitup stop
|
|
414
|
+
unitup stop @backend
|
|
253
415
|
```
|
|
254
416
|
|
|
255
417
|
---
|
|
256
418
|
|
|
257
|
-
### `unitup restart <name>`
|
|
419
|
+
### `unitup restart <name|@group>`
|
|
258
420
|
|
|
259
|
-
Restarts a service:
|
|
421
|
+
Restarts a service or an entire group:
|
|
260
422
|
|
|
261
423
|
```bash
|
|
262
|
-
unitup restart
|
|
424
|
+
unitup restart worker
|
|
425
|
+
unitup restart @backend
|
|
263
426
|
```
|
|
264
427
|
|
|
265
428
|
---
|
|
266
429
|
|
|
267
430
|
### `unitup status <name>`
|
|
268
431
|
|
|
269
|
-
Shows
|
|
432
|
+
Shows compact status summary for the service:
|
|
270
433
|
|
|
271
434
|
```text
|
|
272
|
-
|
|
435
|
+
worker
|
|
273
436
|
|
|
274
437
|
Status: running
|
|
275
|
-
PID:
|
|
276
|
-
Started:
|
|
438
|
+
PID: 14302
|
|
439
|
+
Started: 15 minutes ago
|
|
277
440
|
Restarts: 0
|
|
278
|
-
|
|
279
|
-
|
|
441
|
+
Command: /usr/bin/python3
|
|
442
|
+
Arguments: /home/user/apps/worker.py
|
|
443
|
+
Working directory: /home/user/apps
|
|
280
444
|
```
|
|
281
445
|
|
|
282
|
-
|
|
446
|
+
Pass `--raw` for raw `systemctl status` output:
|
|
283
447
|
|
|
284
448
|
```bash
|
|
285
|
-
unitup status
|
|
449
|
+
unitup status worker --raw
|
|
286
450
|
```
|
|
287
451
|
|
|
288
452
|
---
|
|
289
453
|
|
|
290
454
|
### `unitup logs <name>`
|
|
291
455
|
|
|
292
|
-
View or stream systemd journalctl logs for a service
|
|
456
|
+
View or stream systemd journalctl logs for a service:
|
|
293
457
|
|
|
294
458
|
```bash
|
|
295
|
-
# View last 100 log lines (default)
|
|
296
|
-
unitup logs app
|
|
297
|
-
|
|
298
459
|
# Stream logs in real-time
|
|
299
|
-
unitup logs
|
|
300
|
-
|
|
301
|
-
# View last 50 lines of clean raw console output without systemd metadata prefix
|
|
302
|
-
unitup logs app -c --lines 50
|
|
303
|
-
# or
|
|
304
|
-
unitup logs app --cat --lines 50
|
|
460
|
+
unitup logs worker --follow
|
|
305
461
|
|
|
306
|
-
#
|
|
307
|
-
unitup logs
|
|
462
|
+
# Clean raw console output without systemd timestamp/hostname metadata prefix
|
|
463
|
+
unitup logs worker -c --lines 50
|
|
308
464
|
```
|
|
309
465
|
|
|
310
|
-
**Options:**
|
|
311
|
-
- `-f`, `--follow`: Stream logs in real time.
|
|
312
|
-
- `-n`, `--lines <N>`: Specify number of log lines to show (default: 100).
|
|
313
|
-
- `-c`, `--cat`: Format log output cleanly without systemd timestamp/hostname metadata prefix (`journalctl -o cat`).
|
|
314
|
-
- `--output <format>`: Custom journalctl output mode (e.g. `cat`, `short`, `json`).
|
|
315
|
-
|
|
316
466
|
---
|
|
317
467
|
|
|
318
|
-
### `unitup
|
|
468
|
+
### `unitup failures`
|
|
319
469
|
|
|
320
|
-
Lists all
|
|
470
|
+
Lists all currently failed services with exit codes and restart counts:
|
|
321
471
|
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
api running yes
|
|
325
|
-
worker stopped yes
|
|
326
|
-
cleanup failed no
|
|
472
|
+
```bash
|
|
473
|
+
unitup failures
|
|
327
474
|
```
|
|
328
475
|
|
|
329
476
|
---
|
|
330
477
|
|
|
331
|
-
### `unitup remove <name>`
|
|
478
|
+
### `unitup remove <name|@group>`
|
|
332
479
|
|
|
333
480
|
Stops, disables, and deletes the unit file, then reloads systemd:
|
|
334
481
|
|
|
335
482
|
```bash
|
|
336
|
-
unitup remove
|
|
483
|
+
unitup remove worker
|
|
484
|
+
unitup remove @backend
|
|
337
485
|
```
|
|
338
486
|
|
|
339
|
-
Equivalent systemctl commands executed:
|
|
340
|
-
1. `systemctl --user disable --now unitup-api.service`
|
|
341
|
-
2. Remove `~/.config/systemd/user/unitup-api.service`
|
|
342
|
-
3. `systemctl --user daemon-reload`
|
|
343
|
-
4. `systemctl --user reset-failed`
|
|
344
|
-
|
|
345
487
|
---
|
|
346
488
|
|
|
347
489
|
## User Lingering & Persistence Across Logout
|
|
348
490
|
|
|
349
|
-
|
|
491
|
+
Depending on the Linux distribution and systemd-logind configuration, user services may stop after logout. Enable lingering to allow them to continue running without an active login session:
|
|
350
492
|
|
|
351
493
|
```bash
|
|
352
494
|
loginctl enable-linger $USER
|
|
353
495
|
```
|
|
354
496
|
|
|
355
|
-
`unitup` checks this state in `unitup doctor` and warns if lingering is disabled. `unitup` will never attempt to run `loginctl` or `sudo` automatically on your behalf.
|
|
356
|
-
|
|
357
497
|
---
|
|
358
498
|
|
|
359
499
|
## Programmatic JavaScript & TypeScript API
|
|
360
500
|
|
|
361
501
|
`unitup` includes full TypeScript declaration files (`index.d.ts`). You can import `unitup` directly into JavaScript or TypeScript applications:
|
|
362
502
|
|
|
503
|
+
### Generic `command + args` Example (Language-Agnostic)
|
|
504
|
+
|
|
505
|
+
```ts
|
|
506
|
+
import { createService } from "unitup";
|
|
507
|
+
|
|
508
|
+
await createService({
|
|
509
|
+
name: "worker",
|
|
510
|
+
command: "/usr/bin/python3",
|
|
511
|
+
args: ["/home/user/apps/worker.py"],
|
|
512
|
+
cwd: "/home/user/apps",
|
|
513
|
+
restart: "on-failure",
|
|
514
|
+
start: true
|
|
515
|
+
});
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
### CommonJS Support
|
|
519
|
+
|
|
520
|
+
```js
|
|
521
|
+
const {
|
|
522
|
+
createService,
|
|
523
|
+
startService,
|
|
524
|
+
getServiceStatus
|
|
525
|
+
} = require("unitup");
|
|
526
|
+
|
|
527
|
+
await createService({
|
|
528
|
+
name: "api",
|
|
529
|
+
script: "./server.js",
|
|
530
|
+
start: true
|
|
531
|
+
});
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
### Script & Runtime Example
|
|
535
|
+
|
|
363
536
|
```ts
|
|
364
537
|
import {
|
|
365
538
|
createService,
|
|
@@ -369,33 +542,32 @@ import {
|
|
|
369
542
|
removeService,
|
|
370
543
|
getServiceStatus,
|
|
371
544
|
listServices,
|
|
372
|
-
|
|
545
|
+
inspectService,
|
|
546
|
+
detectRuntime,
|
|
547
|
+
resolveRuntimeConfig,
|
|
548
|
+
isSystemdAvailable
|
|
549
|
+
} from "unitup";
|
|
550
|
+
|
|
551
|
+
import type {
|
|
373
552
|
CreateServiceOptions,
|
|
374
553
|
ServiceStatus
|
|
375
554
|
} from "unitup";
|
|
376
555
|
|
|
377
|
-
// Check if systemd user services are available
|
|
378
556
|
if (await isSystemdAvailable()) {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
557
|
+
// Add a Python worker service via script path
|
|
558
|
+
await createService({
|
|
559
|
+
name: "worker",
|
|
560
|
+
script: "./worker.py",
|
|
561
|
+
runtime: "python",
|
|
383
562
|
env: {
|
|
384
|
-
|
|
385
|
-
PORT: "3000"
|
|
563
|
+
APP_ENV: "production"
|
|
386
564
|
},
|
|
387
|
-
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
// Add a service
|
|
391
|
-
await createService(options);
|
|
565
|
+
start: true
|
|
566
|
+
});
|
|
392
567
|
|
|
393
|
-
//
|
|
394
|
-
await
|
|
395
|
-
|
|
396
|
-
// Get compact status
|
|
397
|
-
const status: ServiceStatus = await getServiceStatus("api");
|
|
398
|
-
console.log(`Service PID: ${status.pid}, Status: ${status.status}`);
|
|
568
|
+
// Inspect service configuration
|
|
569
|
+
const info = await inspectService("worker");
|
|
570
|
+
console.log(`Command: ${info.command}, Status: ${info.status}`);
|
|
399
571
|
|
|
400
572
|
// List all unitup services
|
|
401
573
|
const services = await listServices();
|
|
@@ -405,6 +577,49 @@ if (await isSystemdAvailable()) {
|
|
|
405
577
|
|
|
406
578
|
---
|
|
407
579
|
|
|
580
|
+
## Declarative Project Configuration (Roadmap Preview)
|
|
581
|
+
|
|
582
|
+
Define your application stack declaratively using `unitup.yml` or `unitup.json` and sync it with systemd user services:
|
|
583
|
+
|
|
584
|
+
```yaml
|
|
585
|
+
# unitup.yml
|
|
586
|
+
apps:
|
|
587
|
+
api:
|
|
588
|
+
runtime: node
|
|
589
|
+
script: ./server.js
|
|
590
|
+
env:
|
|
591
|
+
NODE_ENV: production
|
|
592
|
+
PORT: 3000
|
|
593
|
+
start: true
|
|
594
|
+
|
|
595
|
+
worker:
|
|
596
|
+
runtime: python
|
|
597
|
+
script: ./worker.py
|
|
598
|
+
env:
|
|
599
|
+
APP_ENV: production
|
|
600
|
+
|
|
601
|
+
native-service:
|
|
602
|
+
runtime: native
|
|
603
|
+
command: ./server
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
> *Note: Relative script, command, cwd, and env-file paths are resolved relative to the configuration file.*
|
|
607
|
+
|
|
608
|
+
### Planned Declarative Commands:
|
|
609
|
+
|
|
610
|
+
```bash
|
|
611
|
+
# Preview differences between unitup.yml and active systemd units
|
|
612
|
+
unitup diff
|
|
613
|
+
|
|
614
|
+
# Apply unitup.yml configuration and create/update systemd user services
|
|
615
|
+
unitup apply
|
|
616
|
+
|
|
617
|
+
# Perform batch operations on group
|
|
618
|
+
unitup restart @default
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
---
|
|
622
|
+
|
|
408
623
|
## License
|
|
409
624
|
|
|
410
625
|
[MIT](LICENSE)
|