unitup 0.0.9 â 0.0.11
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 +401 -181
- package/docs/index.html +544 -0
- package/index.d.ts +140 -153
- package/package.json +18 -4
- package/src/cli.js +259 -55
- 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 +262 -30
- package/src/unit.js +59 -21
- package/src/utils.js +139 -4
- package/tsconfig.json +13 -0
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,196 @@ 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
|
|
99
183
|
|
|
100
|
-
#
|
|
101
|
-
unitup
|
|
184
|
+
# Elixir
|
|
185
|
+
unitup add app.exs --runtime elixir
|
|
102
186
|
|
|
103
|
-
#
|
|
104
|
-
unitup
|
|
187
|
+
# Native Executable
|
|
188
|
+
unitup add ./server --runtime native --name api
|
|
189
|
+
|
|
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
|
-
|
|
182
|
-
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
### Missing Runtime Handling
|
|
183
298
|
|
|
184
|
-
If
|
|
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`).
|
|
330
|
+
- `--force`, `-f`: Force overwrite of an existing service if it is currently running.
|
|
206
331
|
|
|
207
|
-
Generated unit file example (`~/.config/systemd/user/unitup-
|
|
332
|
+
Generated unit file example (`~/.config/systemd/user/unitup-worker.service`):
|
|
208
333
|
|
|
209
334
|
```ini
|
|
210
335
|
[Unit]
|
|
211
|
-
Description=unitup service:
|
|
336
|
+
Description=unitup service: worker
|
|
212
337
|
After=network.target
|
|
213
338
|
|
|
214
339
|
[Service]
|
|
215
340
|
Type=simple
|
|
216
|
-
|
|
217
|
-
|
|
341
|
+
SyslogIdentifier=unitup-worker
|
|
342
|
+
WorkingDirectory=/home/user/apps
|
|
343
|
+
ExecStart=/usr/bin/python3 /home/user/apps/worker.py
|
|
218
344
|
Restart=on-failure
|
|
219
345
|
RestartSec=3
|
|
220
|
-
EnvironmentFile=/home/user/projects/app/.env
|
|
221
346
|
Environment=PATH="/usr/bin:/usr/local/bin:/bin"
|
|
222
|
-
Environment=
|
|
223
|
-
Environment=PORT="3000"
|
|
347
|
+
Environment=APP_ENV="production"
|
|
224
348
|
|
|
225
349
|
[Install]
|
|
226
350
|
WantedBy=default.target
|
|
@@ -228,138 +352,192 @@ WantedBy=default.target
|
|
|
228
352
|
|
|
229
353
|
---
|
|
230
354
|
|
|
231
|
-
### `unitup
|
|
355
|
+
### `unitup list` / `unitup ls`
|
|
232
356
|
|
|
233
|
-
|
|
357
|
+
Lists all user services managed by `unitup`:
|
|
234
358
|
|
|
235
359
|
```bash
|
|
236
|
-
unitup
|
|
360
|
+
unitup list
|
|
237
361
|
```
|
|
238
362
|
|
|
239
|
-
|
|
363
|
+
```text
|
|
364
|
+
NAME RUNTIME STATUS PID COMMAND
|
|
365
|
+
api node running 14220 node server.js
|
|
366
|
+
worker python running 14302 python3 worker.py
|
|
367
|
+
server native stopped - ./server
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Filter by group:
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
unitup list --group backend
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
### `unitup inspect <name>`
|
|
379
|
+
|
|
380
|
+
View detailed configuration and status overview for a service (without revealing secrets or environment variables):
|
|
381
|
+
|
|
382
|
+
```bash
|
|
383
|
+
unitup inspect worker
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
```text
|
|
387
|
+
Name: worker
|
|
388
|
+
Runtime: python
|
|
389
|
+
Group: backend
|
|
390
|
+
Status: running
|
|
391
|
+
Command: /usr/bin/python3
|
|
392
|
+
Arguments: /home/user/apps/worker.py
|
|
393
|
+
Working directory: /home/user/apps
|
|
394
|
+
Unit: unitup-worker.service
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
### `unitup start <name|@group>`
|
|
400
|
+
|
|
401
|
+
Starts a service or an entire group:
|
|
240
402
|
|
|
241
403
|
```bash
|
|
242
|
-
unitup start
|
|
404
|
+
unitup start worker
|
|
405
|
+
unitup start @backend --enable
|
|
243
406
|
```
|
|
244
407
|
|
|
245
408
|
---
|
|
246
409
|
|
|
247
|
-
### `unitup stop <name>`
|
|
410
|
+
### `unitup stop <name|@group>`
|
|
248
411
|
|
|
249
|
-
Stops a
|
|
412
|
+
Stops a service or an entire group:
|
|
250
413
|
|
|
251
414
|
```bash
|
|
252
|
-
unitup stop
|
|
415
|
+
unitup stop @backend
|
|
253
416
|
```
|
|
254
417
|
|
|
255
418
|
---
|
|
256
419
|
|
|
257
|
-
### `unitup restart <name>`
|
|
420
|
+
### `unitup restart <name|@group>`
|
|
258
421
|
|
|
259
|
-
Restarts a service:
|
|
422
|
+
Restarts a service or an entire group:
|
|
260
423
|
|
|
261
424
|
```bash
|
|
262
|
-
unitup restart
|
|
425
|
+
unitup restart worker
|
|
426
|
+
unitup restart @backend
|
|
263
427
|
```
|
|
264
428
|
|
|
265
429
|
---
|
|
266
430
|
|
|
267
431
|
### `unitup status <name>`
|
|
268
432
|
|
|
269
|
-
Shows
|
|
433
|
+
Shows compact status summary for the service:
|
|
270
434
|
|
|
271
435
|
```text
|
|
272
|
-
|
|
436
|
+
worker
|
|
273
437
|
|
|
274
438
|
Status: running
|
|
275
|
-
PID:
|
|
276
|
-
Started:
|
|
439
|
+
PID: 14302
|
|
440
|
+
Started: 15 minutes ago
|
|
277
441
|
Restarts: 0
|
|
278
|
-
|
|
279
|
-
|
|
442
|
+
Command: /usr/bin/python3
|
|
443
|
+
Arguments: /home/user/apps/worker.py
|
|
444
|
+
Working directory: /home/user/apps
|
|
280
445
|
```
|
|
281
446
|
|
|
282
|
-
|
|
447
|
+
Pass `--raw` for raw `systemctl status` output:
|
|
283
448
|
|
|
284
449
|
```bash
|
|
285
|
-
unitup status
|
|
450
|
+
unitup status worker --raw
|
|
286
451
|
```
|
|
287
452
|
|
|
288
453
|
---
|
|
289
454
|
|
|
290
455
|
### `unitup logs <name>`
|
|
291
456
|
|
|
292
|
-
View or stream systemd journalctl logs for a service
|
|
457
|
+
View or stream systemd journalctl logs for a service:
|
|
293
458
|
|
|
294
459
|
```bash
|
|
295
|
-
# View last 100 log lines (default)
|
|
296
|
-
unitup logs app
|
|
297
|
-
|
|
298
460
|
# 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
|
|
461
|
+
unitup logs worker --follow
|
|
305
462
|
|
|
306
|
-
#
|
|
307
|
-
unitup logs
|
|
463
|
+
# Clean raw console output without systemd timestamp/hostname metadata prefix
|
|
464
|
+
unitup logs worker -c --lines 50
|
|
308
465
|
```
|
|
309
466
|
|
|
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
467
|
---
|
|
317
468
|
|
|
318
|
-
### `unitup
|
|
469
|
+
### `unitup failures`
|
|
319
470
|
|
|
320
|
-
Lists all
|
|
471
|
+
Lists all currently failed services with exit codes and restart counts:
|
|
321
472
|
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
api running yes
|
|
325
|
-
worker stopped yes
|
|
326
|
-
cleanup failed no
|
|
473
|
+
```bash
|
|
474
|
+
unitup failures
|
|
327
475
|
```
|
|
328
476
|
|
|
329
477
|
---
|
|
330
478
|
|
|
331
|
-
### `unitup remove <name>`
|
|
479
|
+
### `unitup remove <name|@group>`
|
|
332
480
|
|
|
333
|
-
Stops, disables, and deletes the unit file, then reloads systemd
|
|
481
|
+
Stops, disables, and deletes the unit file, then reloads systemd. If the service is currently running, `unitup` prevents accidental deletion and requires `--force` / `-f`:
|
|
334
482
|
|
|
335
483
|
```bash
|
|
336
|
-
|
|
337
|
-
|
|
484
|
+
# Remove stopped service
|
|
485
|
+
unitup remove worker
|
|
338
486
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
4. `systemctl --user reset-failed`
|
|
487
|
+
# Force remove an actively running service or group
|
|
488
|
+
unitup remove worker --force
|
|
489
|
+
unitup remove @backend -f
|
|
490
|
+
```
|
|
344
491
|
|
|
345
492
|
---
|
|
346
493
|
|
|
347
494
|
## User Lingering & Persistence Across Logout
|
|
348
495
|
|
|
349
|
-
|
|
496
|
+
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
497
|
|
|
351
498
|
```bash
|
|
352
499
|
loginctl enable-linger $USER
|
|
353
500
|
```
|
|
354
501
|
|
|
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
502
|
---
|
|
358
503
|
|
|
359
504
|
## Programmatic JavaScript & TypeScript API
|
|
360
505
|
|
|
361
506
|
`unitup` includes full TypeScript declaration files (`index.d.ts`). You can import `unitup` directly into JavaScript or TypeScript applications:
|
|
362
507
|
|
|
508
|
+
### Generic `command + args` Example (Language-Agnostic)
|
|
509
|
+
|
|
510
|
+
```ts
|
|
511
|
+
import { createService } from "unitup";
|
|
512
|
+
|
|
513
|
+
await createService({
|
|
514
|
+
name: "worker",
|
|
515
|
+
command: "/usr/bin/python3",
|
|
516
|
+
args: ["/home/user/apps/worker.py"],
|
|
517
|
+
cwd: "/home/user/apps",
|
|
518
|
+
restart: "on-failure",
|
|
519
|
+
start: true
|
|
520
|
+
});
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
### CommonJS Support
|
|
524
|
+
|
|
525
|
+
```js
|
|
526
|
+
const {
|
|
527
|
+
createService,
|
|
528
|
+
startService,
|
|
529
|
+
getServiceStatus
|
|
530
|
+
} = require("unitup");
|
|
531
|
+
|
|
532
|
+
await createService({
|
|
533
|
+
name: "api",
|
|
534
|
+
script: "./server.js",
|
|
535
|
+
start: true
|
|
536
|
+
});
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
### Script & Runtime Example
|
|
540
|
+
|
|
363
541
|
```ts
|
|
364
542
|
import {
|
|
365
543
|
createService,
|
|
@@ -369,33 +547,32 @@ import {
|
|
|
369
547
|
removeService,
|
|
370
548
|
getServiceStatus,
|
|
371
549
|
listServices,
|
|
372
|
-
|
|
550
|
+
inspectService,
|
|
551
|
+
detectRuntime,
|
|
552
|
+
resolveRuntimeConfig,
|
|
553
|
+
isSystemdAvailable
|
|
554
|
+
} from "unitup";
|
|
555
|
+
|
|
556
|
+
import type {
|
|
373
557
|
CreateServiceOptions,
|
|
374
558
|
ServiceStatus
|
|
375
559
|
} from "unitup";
|
|
376
560
|
|
|
377
|
-
// Check if systemd user services are available
|
|
378
561
|
if (await isSystemdAvailable()) {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
562
|
+
// Add a Python worker service via script path
|
|
563
|
+
await createService({
|
|
564
|
+
name: "worker",
|
|
565
|
+
script: "./worker.py",
|
|
566
|
+
runtime: "python",
|
|
383
567
|
env: {
|
|
384
|
-
|
|
385
|
-
PORT: "3000"
|
|
568
|
+
APP_ENV: "production"
|
|
386
569
|
},
|
|
387
|
-
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
// Add a service
|
|
391
|
-
await createService(options);
|
|
570
|
+
start: true
|
|
571
|
+
});
|
|
392
572
|
|
|
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}`);
|
|
573
|
+
// Inspect service configuration
|
|
574
|
+
const info = await inspectService("worker");
|
|
575
|
+
console.log(`Command: ${info.command}, Status: ${info.status}`);
|
|
399
576
|
|
|
400
577
|
// List all unitup services
|
|
401
578
|
const services = await listServices();
|
|
@@ -405,6 +582,49 @@ if (await isSystemdAvailable()) {
|
|
|
405
582
|
|
|
406
583
|
---
|
|
407
584
|
|
|
585
|
+
## Declarative Project Configuration (Roadmap Preview)
|
|
586
|
+
|
|
587
|
+
Define your application stack declaratively using `unitup.yml` or `unitup.json` and sync it with systemd user services:
|
|
588
|
+
|
|
589
|
+
```yaml
|
|
590
|
+
# unitup.yml
|
|
591
|
+
apps:
|
|
592
|
+
api:
|
|
593
|
+
runtime: node
|
|
594
|
+
script: ./server.js
|
|
595
|
+
env:
|
|
596
|
+
NODE_ENV: production
|
|
597
|
+
PORT: 3000
|
|
598
|
+
start: true
|
|
599
|
+
|
|
600
|
+
worker:
|
|
601
|
+
runtime: python
|
|
602
|
+
script: ./worker.py
|
|
603
|
+
env:
|
|
604
|
+
APP_ENV: production
|
|
605
|
+
|
|
606
|
+
native-service:
|
|
607
|
+
runtime: native
|
|
608
|
+
command: ./server
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
> *Note: Relative script, command, cwd, and env-file paths are resolved relative to the configuration file.*
|
|
612
|
+
|
|
613
|
+
### Planned Declarative Commands:
|
|
614
|
+
|
|
615
|
+
```bash
|
|
616
|
+
# Preview differences between unitup.yml and active systemd units
|
|
617
|
+
unitup diff
|
|
618
|
+
|
|
619
|
+
# Apply unitup.yml configuration and create/update systemd user services
|
|
620
|
+
unitup apply
|
|
621
|
+
|
|
622
|
+
# Perform batch operations on group
|
|
623
|
+
unitup restart @default
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
---
|
|
627
|
+
|
|
408
628
|
## License
|
|
409
629
|
|
|
410
630
|
[MIT](LICENSE)
|