devex 0.3.5
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.
- checksums.yaml +7 -0
- data/.obsidian/app.json +6 -0
- data/.obsidian/appearance.json +4 -0
- data/.obsidian/community-plugins.json +5 -0
- data/.obsidian/core-plugins.json +33 -0
- data/.obsidian/plugins/obsidian-minimal-settings/data.json +34 -0
- data/.obsidian/plugins/obsidian-minimal-settings/main.js +8 -0
- data/.obsidian/plugins/obsidian-minimal-settings/manifest.json +11 -0
- data/.obsidian/plugins/obsidian-style-settings/data.json +15 -0
- data/.obsidian/plugins/obsidian-style-settings/main.js +165 -0
- data/.obsidian/plugins/obsidian-style-settings/manifest.json +10 -0
- data/.obsidian/plugins/obsidian-style-settings/styles.css +243 -0
- data/.obsidian/plugins/table-editor-obsidian/data.json +6 -0
- data/.obsidian/plugins/table-editor-obsidian/main.js +236 -0
- data/.obsidian/plugins/table-editor-obsidian/manifest.json +17 -0
- data/.obsidian/plugins/table-editor-obsidian/styles.css +78 -0
- data/.obsidian/themes/AnuPpuccin/manifest.json +7 -0
- data/.obsidian/themes/AnuPpuccin/theme.css +9080 -0
- data/.obsidian/themes/Minimal/manifest.json +8 -0
- data/.obsidian/themes/Minimal/theme.css +2251 -0
- data/.rubocop.yml +231 -0
- data/CHANGELOG.md +97 -0
- data/LICENSE +21 -0
- data/README.md +314 -0
- data/Rakefile +13 -0
- data/devex-logo.jpg +0 -0
- data/docs/developing-tools.md +1000 -0
- data/docs/ref/agent-mode.md +46 -0
- data/docs/ref/cli-interface.md +60 -0
- data/docs/ref/configuration.md +46 -0
- data/docs/ref/design-philosophy.md +17 -0
- data/docs/ref/error-handling.md +38 -0
- data/docs/ref/io-handling.md +88 -0
- data/docs/ref/signals.md +141 -0
- data/docs/ref/temporal-software-theory.md +790 -0
- data/exe/dx +52 -0
- data/lib/devex/builtins/.index.rb +10 -0
- data/lib/devex/builtins/debug.rb +43 -0
- data/lib/devex/builtins/format.rb +44 -0
- data/lib/devex/builtins/gem.rb +77 -0
- data/lib/devex/builtins/lint.rb +61 -0
- data/lib/devex/builtins/test.rb +76 -0
- data/lib/devex/builtins/version.rb +156 -0
- data/lib/devex/cli.rb +340 -0
- data/lib/devex/context.rb +433 -0
- data/lib/devex/core/configuration.rb +136 -0
- data/lib/devex/core.rb +79 -0
- data/lib/devex/dirs.rb +210 -0
- data/lib/devex/dsl.rb +100 -0
- data/lib/devex/exec/controller.rb +245 -0
- data/lib/devex/exec/result.rb +229 -0
- data/lib/devex/exec.rb +662 -0
- data/lib/devex/loader.rb +136 -0
- data/lib/devex/output.rb +257 -0
- data/lib/devex/project_paths.rb +309 -0
- data/lib/devex/support/ansi.rb +437 -0
- data/lib/devex/support/core_ext.rb +560 -0
- data/lib/devex/support/global.rb +68 -0
- data/lib/devex/support/path.rb +357 -0
- data/lib/devex/support.rb +71 -0
- data/lib/devex/template_helpers.rb +136 -0
- data/lib/devex/templates/debug.erb +24 -0
- data/lib/devex/tool.rb +374 -0
- data/lib/devex/version.rb +5 -0
- data/lib/devex/working_dir.rb +99 -0
- data/lib/devex.rb +158 -0
- data/ruby-project-template/.gitignore +0 -0
- data/ruby-project-template/Gemfile +0 -0
- data/ruby-project-template/README.md +0 -0
- data/ruby-project-template/docs/README.md +0 -0
- data/sig/devex.rbs +4 -0
- metadata +122 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
## AI Agent Considerations
|
|
2
|
+
|
|
3
|
+
### Auto-Detection of Agent Mode
|
|
4
|
+
Trigger agent mode when:
|
|
5
|
+
- Non-interactive terminal (`!isatty()`)
|
|
6
|
+
- CI environment variable set
|
|
7
|
+
- Streams are merged (stdout==stderr)
|
|
8
|
+
- `MYTOOL_AGENT_MODE=1` environment variable
|
|
9
|
+
- `--format=json` or other structured format requested
|
|
10
|
+
|
|
11
|
+
### Agent Mode Behavior
|
|
12
|
+
- No progress indicators or spinners
|
|
13
|
+
- No colors or text formatting
|
|
14
|
+
- Structured output preferred
|
|
15
|
+
- No interactive prompts (fail instead)
|
|
16
|
+
- Deterministic output ordering
|
|
17
|
+
- Include metadata in structured output
|
|
18
|
+
|
|
19
|
+
### Recommended Agent Invocation
|
|
20
|
+
```bash
|
|
21
|
+
# Explicit agent-friendly invocation
|
|
22
|
+
mytool [command] \
|
|
23
|
+
--format=json \
|
|
24
|
+
--no-progress \
|
|
25
|
+
--no-color \
|
|
26
|
+
--batch
|
|
27
|
+
|
|
28
|
+
# Or via environment
|
|
29
|
+
export MYTOOL_AGENT_MODE=1
|
|
30
|
+
mytool [command]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Help for Agents
|
|
34
|
+
```bash
|
|
35
|
+
# Machine-readable help
|
|
36
|
+
mytool --help --format=json
|
|
37
|
+
|
|
38
|
+
# List available commands/flags
|
|
39
|
+
mytool --list-commands
|
|
40
|
+
mytool --list-flags
|
|
41
|
+
mytool subcommand --list-flags
|
|
42
|
+
|
|
43
|
+
# Generate shell completions
|
|
44
|
+
mytool --generate-completion bash|zsh|fish
|
|
45
|
+
```
|
|
46
|
+
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
## Command-Line Interface
|
|
2
|
+
|
|
3
|
+
### Universal Flags
|
|
4
|
+
Every tool should support:
|
|
5
|
+
```bash
|
|
6
|
+
-h, --help # Show help
|
|
7
|
+
-v, --verbose # Increase verbosity (stackable: -vvv)
|
|
8
|
+
-q, --quiet # Suppress non-error output
|
|
9
|
+
--version # Show version and exit
|
|
10
|
+
--format=FORMAT # Output format (json|text|csv|tsv|yaml)
|
|
11
|
+
--no-color # Disable colored output
|
|
12
|
+
--color=auto|always|never # Color output control
|
|
13
|
+
--dry-run # Preview what would be done
|
|
14
|
+
--debug # Maximum verbosity for debugging
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Flag Conventions
|
|
18
|
+
```bash
|
|
19
|
+
# Short flags (single dash, single letter)
|
|
20
|
+
-v # Boolean flag
|
|
21
|
+
-f filename # With argument (space)
|
|
22
|
+
-ffilename # With argument (no space)
|
|
23
|
+
-abc # Combined boolean flags (equals -a -b -c)
|
|
24
|
+
|
|
25
|
+
# Long flags (double dash, descriptive)
|
|
26
|
+
--verbose # Boolean flag
|
|
27
|
+
--file=filename # With argument (equals)
|
|
28
|
+
--file filename # With argument (space)
|
|
29
|
+
|
|
30
|
+
# Special conventions
|
|
31
|
+
-- # Stop processing flags
|
|
32
|
+
- # Stdin/stdout placeholder
|
|
33
|
+
@filename # Read arguments from file
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Exit Codes
|
|
37
|
+
```bash
|
|
38
|
+
0 Success
|
|
39
|
+
1 General errors
|
|
40
|
+
2 Misuse of shell command (invalid options, missing arguments)
|
|
41
|
+
64 Command line usage error (EX_USAGE)
|
|
42
|
+
65 Data format error (EX_DATAERR)
|
|
43
|
+
66 Cannot open input (EX_NOINPUT)
|
|
44
|
+
67 Addressee unknown (EX_NOUSER)
|
|
45
|
+
68 Host name unknown (EX_NOHOST)
|
|
46
|
+
69 Service unavailable (EX_UNAVAILABLE)
|
|
47
|
+
70 Internal software error (EX_SOFTWARE)
|
|
48
|
+
71 System error (EX_OSERR)
|
|
49
|
+
72 Critical OS file missing (EX_OSFILE)
|
|
50
|
+
73 Can't create output file (EX_CANTCREAT)
|
|
51
|
+
74 I/O error (EX_IOERR)
|
|
52
|
+
75 Temporary failure (EX_TEMPFAIL)
|
|
53
|
+
76 Remote error in protocol (EX_PROTOCOL)
|
|
54
|
+
77 Permission denied (EX_NOPERM)
|
|
55
|
+
78 Configuration error (EX_CONFIG)
|
|
56
|
+
126 Command found but not executable
|
|
57
|
+
127 Command not found
|
|
58
|
+
128+n Fatal signal n (e.g., 130 = 128+2 = SIGINT)
|
|
59
|
+
```
|
|
60
|
+
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
## Configuration Management
|
|
2
|
+
|
|
3
|
+
### Precedence Order (highest to lowest)
|
|
4
|
+
1. Command-line flags
|
|
5
|
+
2. Environment variables (`MYTOOL_*` prefix)
|
|
6
|
+
3. Local config file (`./.mytoolrc` or `./mytool.{json,yaml,toml}`)
|
|
7
|
+
4. User config file (`~/.config/mytool/config`)
|
|
8
|
+
5. System config (`/etc/mytool/config`)
|
|
9
|
+
6. Built-in defaults
|
|
10
|
+
|
|
11
|
+
### Configuration File Locations
|
|
12
|
+
```bash
|
|
13
|
+
# Standard locations (XDG Base Directory Specification)
|
|
14
|
+
~/.config/mytool/ # User config directory
|
|
15
|
+
~/.local/share/mytool/ # User data directory
|
|
16
|
+
~/.cache/mytool/ # User cache directory
|
|
17
|
+
/etc/mytool/ # System config directory
|
|
18
|
+
|
|
19
|
+
# Legacy support (if needed)
|
|
20
|
+
~/.mytool # Old-style dotfile
|
|
21
|
+
~/.mytool.conf # Old-style config
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Environment Variables
|
|
25
|
+
```bash
|
|
26
|
+
# Naming convention
|
|
27
|
+
MYTOOL_CONFIG_FILE=/path/to/config
|
|
28
|
+
MYTOOL_LOG_LEVEL=debug
|
|
29
|
+
MYTOOL_FORMAT=json
|
|
30
|
+
MYTOOL_NO_COLOR=1
|
|
31
|
+
|
|
32
|
+
# Special variables
|
|
33
|
+
MYTOOL_HOME # Override base directory
|
|
34
|
+
MYTOOL_DISABLE_UPDATE # Disable auto-update checks
|
|
35
|
+
MYTOOL_AGENT_MODE=1 # Force agent mode
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Working Directory Behavior
|
|
39
|
+
1. Explicit paths in arguments are relative to CWD
|
|
40
|
+
2. Config files search order:
|
|
41
|
+
- Relative to CWD first (project-specific)
|
|
42
|
+
- Relative to script location (bundled configs)
|
|
43
|
+
- Standard system locations
|
|
44
|
+
3. Use `--config=PATH` to override
|
|
45
|
+
4. Document this behavior clearly
|
|
46
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
## Core Design Philosophy
|
|
2
|
+
|
|
3
|
+
### Unix Philosophy Foundations
|
|
4
|
+
- **Do one thing well** - Each utility should have a single, clear purpose
|
|
5
|
+
- **Composability** - Design for chaining with other tools via pipes
|
|
6
|
+
- **Text streams as universal interface** - With structured output options for machines
|
|
7
|
+
- **Silence is golden** - No output on success unless explicitly requested
|
|
8
|
+
- **Fail fast and explicitly** - Clear, immediate errors with proper exit codes
|
|
9
|
+
- **Idempotency** - Operations should be idempotent where possible
|
|
10
|
+
|
|
11
|
+
### AI Agent Design Principles
|
|
12
|
+
- **Predictable, deterministic behavior** - Same inputs always produce same outputs
|
|
13
|
+
- **Structured output modes** - JSON/TSV/CSV options via flags
|
|
14
|
+
- **Machine-readable errors** - Parseable error formats, not just human prose
|
|
15
|
+
- **Explicit verbosity control** - Clear separation of operational output vs diagnostic info
|
|
16
|
+
- **No interactive prompts in non-interactive mode** - Fail fast instead
|
|
17
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
## Error Handling
|
|
2
|
+
|
|
3
|
+
### Error Message Format
|
|
4
|
+
|
|
5
|
+
#### Human-Readable (default)
|
|
6
|
+
```
|
|
7
|
+
Error: Failed to parse configuration file
|
|
8
|
+
File: /home/user/.config/mytool/config.yaml
|
|
9
|
+
Line: 42
|
|
10
|
+
Reason: Unexpected token ':'
|
|
11
|
+
|
|
12
|
+
Try 'mytool --help' for more information.
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
#### Machine-Readable (--format=json)
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"error": {
|
|
19
|
+
"code": "CONFIG_PARSE_ERROR",
|
|
20
|
+
"message": "Failed to parse configuration file",
|
|
21
|
+
"details": {
|
|
22
|
+
"file": "/home/user/.config/mytool/config.yaml",
|
|
23
|
+
"line": 42,
|
|
24
|
+
"column": 15,
|
|
25
|
+
"token": ":"
|
|
26
|
+
},
|
|
27
|
+
"help": "https://docs.example.com/errors/CONFIG_PARSE_ERROR"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Error Categories
|
|
33
|
+
- **Usage Errors**: Invalid flags, missing arguments
|
|
34
|
+
- **Input Errors**: Malformed data, missing files
|
|
35
|
+
- **Runtime Errors**: Network failures, resource exhaustion
|
|
36
|
+
- **Configuration Errors**: Invalid config, missing required settings
|
|
37
|
+
- **Permission Errors**: Insufficient privileges
|
|
38
|
+
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
## Input/Output Handling
|
|
2
|
+
|
|
3
|
+
### Stream Usage
|
|
4
|
+
- **stdin**: Primary input data (when no file specified)
|
|
5
|
+
- **stdout**: Primary output, pipeable data only
|
|
6
|
+
- **stderr**: Errors, warnings, progress indicators, diagnostics
|
|
7
|
+
|
|
8
|
+
### Core Principle
|
|
9
|
+
`stdout` should be immediately pipeable - never mix status messages with data output.
|
|
10
|
+
|
|
11
|
+
### Stream Behavior Examples
|
|
12
|
+
```bash
|
|
13
|
+
# Good - clean separation
|
|
14
|
+
$ mytool process data.txt > output.txt
|
|
15
|
+
Processing 1000 records... # to stderr
|
|
16
|
+
[progress bar] # to stderr
|
|
17
|
+
Done! # to stderr
|
|
18
|
+
# output.txt contains only data
|
|
19
|
+
|
|
20
|
+
# Bad - mixed output
|
|
21
|
+
$ mytool process data.txt > output.txt
|
|
22
|
+
Processing 1000 records... # to stdout (contaminating)
|
|
23
|
+
{"data": "actual output"} # to stdout
|
|
24
|
+
Done! # to stdout (contaminating)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Handling Merged Streams (2>&1)
|
|
28
|
+
|
|
29
|
+
#### Detection
|
|
30
|
+
```python
|
|
31
|
+
import os
|
|
32
|
+
import sys
|
|
33
|
+
|
|
34
|
+
streams_merged = os.fstat(sys.stdout.fileno()) == os.fstat(sys.stderr.fileno())
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
#### Adaptation Strategies
|
|
38
|
+
|
|
39
|
+
1. **Automatic Mode Switching**
|
|
40
|
+
```bash
|
|
41
|
+
# When streams merged detected:
|
|
42
|
+
- Suppress all progress/status to stderr
|
|
43
|
+
- Switch to structured output if available
|
|
44
|
+
- Use line prefixes for critical messages
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
2. **Prefixed Output Pattern**
|
|
48
|
+
```
|
|
49
|
+
ERROR: Failed to process record 5
|
|
50
|
+
WARNING: Using deprecated format
|
|
51
|
+
DATA: {"actual": "data", "here": true}
|
|
52
|
+
PROGRESS: 50/100 records processed
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
3. **Structured Output Mode**
|
|
56
|
+
```json
|
|
57
|
+
{"type":"progress","current":0,"total":1000}
|
|
58
|
+
{"type":"data","content":{"id":1,"value":"foo"}}
|
|
59
|
+
{"type":"warning","message":"Deprecated field 'bar'"}
|
|
60
|
+
{"type":"data","content":{"id":2,"value":"baz"}}
|
|
61
|
+
{"type":"result","status":"success","records":1000}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Interactive vs Non-Interactive
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Detection
|
|
68
|
+
if [ -t 0 ] && [ -t 1 ]; then
|
|
69
|
+
# Interactive: colors, prompts, progress bars OK
|
|
70
|
+
else
|
|
71
|
+
# Non-interactive: plain output, no prompts
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
# Override flags
|
|
75
|
+
--interactive # Force interactive mode
|
|
76
|
+
--batch # Force non-interactive mode
|
|
77
|
+
--no-tty # Assume no terminal
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Pipeline Safety
|
|
81
|
+
```bash
|
|
82
|
+
# Guarantee clean stdout for pipelines
|
|
83
|
+
--pipe # Equivalent to: --quiet --format=text --no-progress
|
|
84
|
+
|
|
85
|
+
# Usage
|
|
86
|
+
mytool process --pipe < input.txt | next-tool
|
|
87
|
+
```
|
|
88
|
+
|
data/docs/ref/signals.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
## Signal Handling
|
|
2
|
+
|
|
3
|
+
### Standard Signal Behavior
|
|
4
|
+
|
|
5
|
+
#### Core Signals
|
|
6
|
+
```bash
|
|
7
|
+
SIGINT (2) # Ctrl-C: Graceful interruption
|
|
8
|
+
SIGTERM (15) # Graceful termination request
|
|
9
|
+
SIGQUIT (3) # Ctrl-\: Quit with core dump
|
|
10
|
+
SIGHUP (1) # Hangup: Reload configuration
|
|
11
|
+
SIGUSR1 (10) # User-defined: Often toggle debug
|
|
12
|
+
SIGUSR2 (12) # User-defined: Often rotate logs
|
|
13
|
+
SIGPIPE (13) # Broken pipe: Handle gracefully
|
|
14
|
+
SIGALRM (14) # Timer expired
|
|
15
|
+
SIGCHLD (17) # Child process status change
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
#### SIGINT (Ctrl-C) Handling
|
|
19
|
+
```bash
|
|
20
|
+
# Graceful interruption pattern
|
|
21
|
+
handle_sigint() {
|
|
22
|
+
echo "Interrupt received, cleaning up..." >&2
|
|
23
|
+
cleanup_temp_files
|
|
24
|
+
save_progress
|
|
25
|
+
exit 130 # 128 + 2 (SIGINT)
|
|
26
|
+
}
|
|
27
|
+
trap handle_sigint INT
|
|
28
|
+
|
|
29
|
+
# Progressive interruption
|
|
30
|
+
First Ctrl-C: "Gracefully stopping... (press again to force)"
|
|
31
|
+
Second Ctrl-C: "Force stopping..."
|
|
32
|
+
Third Ctrl-C: Immediate termination
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### EOF (Ctrl-D) Handling
|
|
36
|
+
```bash
|
|
37
|
+
# Ctrl-D sends EOF, not a signal
|
|
38
|
+
# Proper handling in interactive mode:
|
|
39
|
+
while IFS= read -r line; do
|
|
40
|
+
process_line "$line"
|
|
41
|
+
done
|
|
42
|
+
# Ctrl-D here ends input gracefully
|
|
43
|
+
|
|
44
|
+
# Detection and response
|
|
45
|
+
if [ -t 0 ]; then # Interactive terminal
|
|
46
|
+
echo "Press Ctrl-D or type 'exit' to quit"
|
|
47
|
+
fi
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
#### SIGHUP Configuration Reload
|
|
51
|
+
```bash
|
|
52
|
+
# Standard SIGHUP behavior
|
|
53
|
+
handle_sighup() {
|
|
54
|
+
echo "Reloading configuration..." >&2
|
|
55
|
+
reload_config
|
|
56
|
+
reopen_log_files # Important for log rotation
|
|
57
|
+
reset_connections
|
|
58
|
+
}
|
|
59
|
+
trap handle_sighup HUP
|
|
60
|
+
|
|
61
|
+
# Usage
|
|
62
|
+
kill -HUP $(pidof mytool) # Reload config
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Signal Safety
|
|
66
|
+
|
|
67
|
+
#### Critical Section Protection
|
|
68
|
+
```bash
|
|
69
|
+
# Prevent interruption during critical operations
|
|
70
|
+
critical_section_start() {
|
|
71
|
+
trap '' INT TERM # Ignore signals
|
|
72
|
+
CRITICAL=1
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
critical_section_end() {
|
|
76
|
+
CRITICAL=0
|
|
77
|
+
trap handle_sigint INT
|
|
78
|
+
trap handle_sigterm TERM
|
|
79
|
+
# Process any pending signals
|
|
80
|
+
if [ -n "$PENDING_SIGNAL" ]; then
|
|
81
|
+
kill -s "$PENDING_SIGNAL" $$
|
|
82
|
+
fi
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
#### Cleanup Guarantees
|
|
87
|
+
```bash
|
|
88
|
+
# Ensure cleanup happens
|
|
89
|
+
cleanup() {
|
|
90
|
+
local exit_code=$?
|
|
91
|
+
set +e # Don't exit on errors during cleanup
|
|
92
|
+
|
|
93
|
+
# Remove temp files
|
|
94
|
+
rm -f "$TMPFILE"
|
|
95
|
+
|
|
96
|
+
# Release locks
|
|
97
|
+
flock -u 9 2>/dev/null
|
|
98
|
+
|
|
99
|
+
# Restore terminal settings
|
|
100
|
+
stty "$SAVED_STTY" 2>/dev/null
|
|
101
|
+
|
|
102
|
+
# Kill child processes
|
|
103
|
+
jobs -p | xargs kill 2>/dev/null
|
|
104
|
+
|
|
105
|
+
exit $exit_code
|
|
106
|
+
}
|
|
107
|
+
trap cleanup EXIT INT TERM
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Signal Propagation
|
|
111
|
+
|
|
112
|
+
#### Child Process Management
|
|
113
|
+
```bash
|
|
114
|
+
# Propagate signals to children
|
|
115
|
+
handle_signal() {
|
|
116
|
+
local signal=$1
|
|
117
|
+
# Send signal to process group
|
|
118
|
+
kill -$signal 0 # 0 means current process group
|
|
119
|
+
wait # Wait for children to terminate
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
# Start processes in same group
|
|
123
|
+
set -m # Enable job control
|
|
124
|
+
mytool &
|
|
125
|
+
child_pid=$!
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### Background Job Handling
|
|
129
|
+
```bash
|
|
130
|
+
# Proper daemon signal handling
|
|
131
|
+
--daemon
|
|
132
|
+
--pidfile=/var/run/mytool.pid
|
|
133
|
+
--signal-forward # Forward signals to workers
|
|
134
|
+
|
|
135
|
+
# Signal commands
|
|
136
|
+
mytool signal reload # Send SIGHUP
|
|
137
|
+
mytool signal stop # Send SIGTERM
|
|
138
|
+
mytool signal kill # Send SIGKILL
|
|
139
|
+
mytool signal status # Check if responding
|
|
140
|
+
```
|
|
141
|
+
|