Early exit pattern matching for command output with fast error detection
Project description
earlyexit ๐
Early exit pattern matching for command output - Exit immediately when a pattern is matched, with timeout support.
Implements the early error detection pattern for faster feedback during long-running commands, CI/CD pipelines, and log monitoring.
๐ฏ Purpose
Traditional grep processes the entire input stream. earlyexit exits immediately on the first match, saving time and providing instant feedback for errors.
Perfect for:
- ๐ง Long-running build processes
- ๐งช Test suites
- ๐ Deployment pipelines
- ๐ Log monitoring
- โฑ๏ธ Time-sensitive operations
๐ฆ Installation
# Install from PyPI (when published)
pip install earlyexit
# Install from source
git clone https://github.com/rsleedbx/earlyexit
cd earlyexit
pip install -e .
# With Perl-compatible regex support
pip install -e ".[perl]"
๐ Quick Start
# Exit immediately on first error (with 30s timeout)
long_running_command | earlyexit -t 30 'Error|Failed'
# Monitor Terraform apply
terraform apply | earlyexit -t 600 -i 'error'
# Stop after 3 test failures
pytest | earlyexit -m 3 'FAILED'
# Check if service is healthy (invert match)
health_check_loop | earlyexit -v 'OK' -t 10
๐ Usage
earlyexit [OPTIONS] PATTERN
Arguments:
PATTERN Regular expression pattern to match
Options:
-t, --timeout SECONDS Timeout in seconds (default: no timeout)
-m, --max-count NUM Stop after NUM matches (default: 1)
-i, --ignore-case Case-insensitive matching
-E, --extended-regexp Extended regex (Python re module, default)
-P, --perl-regexp Perl-compatible regex (requires regex module)
-v, --invert-match Invert match - select non-matching lines
-q, --quiet Quiet mode - suppress output, only exit code
-n, --line-number Prefix output with line number
--color WHEN Colorize output: always, auto (default), never
--version Show version
-h, --help Show help message
Exit Codes:
0 - Pattern matched (error detected)
1 - No match found (success)
2 - Timeout exceeded
3 - Other error
๐ก Examples
Example 1: Terraform Operations
# Exit immediately on error, 10min timeout
terraform apply -auto-approve 2>&1 | \
stdbuf -o0 tee terraform.log | \
earlyexit -t 600 -i 'error'
if [ $? -eq 0 ]; then
echo "โ Terraform failed - check terraform.log"
exit 1
elif [ $? -eq 2 ]; then
echo "โฑ๏ธ Terraform timed out after 10 minutes"
exit 2
else
echo "โ
Terraform completed successfully"
fi
Example 2: Database Provisioning
# Monitor database creation, fail fast on errors
vapordb create --cloud aws --db mysql 2>&1 | \
tee /tmp/db_create.log | \
earlyexit -t 1800 'Error|Failed|Exception'
case $? in
0) echo "โ Database creation failed"; exit 1 ;;
1) echo "โ
Database created successfully" ;;
2) echo "โฑ๏ธ Creation timed out after 30 minutes"; exit 2 ;;
esac
Example 3: Test Suite Monitoring
# Stop after 5 test failures
pytest -v | earlyexit -m 5 'FAILED'
if [ $? -eq 0 ]; then
echo "โ Tests failed - stopping early"
exit 1
fi
Example 4: CI/CD Pipeline
# Monitor build output for errors
./build.sh 2>&1 | \
stdbuf -o0 tee build.log | \
earlyexit -t 3600 -iE '(error|fatal|exception)'
exit $? # Propagate exit code
Example 5: Log Monitoring
# Monitor application logs in real-time
tail -f /var/log/app.log | \
earlyexit -t 300 -i 'error|exception|fatal'
if [ $? -eq 0 ]; then
echo "๐จ Error detected in logs!"
# Send alert, trigger remediation, etc.
fi
Example 6: Health Check
# Ensure service stays healthy for 60 seconds
# Exit if "OK" stops appearing (invert match)
while true; do
curl -s http://localhost:8080/health
sleep 1
done | earlyexit -v 'OK' -t 60
if [ $? -eq 0 ]; then
echo "โ Health check failed - 'OK' not found"
exit 1
fi
Example 7: Multiple Patterns
# Match any of several error conditions
app_command | earlyexit -E '(ERROR|FATAL|EXCEPTION|SEGFAULT|PANIC)'
Example 8: With Line Numbers
# Show line numbers for matched errors
long_log_file | earlyexit -n -i 'error'
# Output: 1234:ERROR: Connection failed
๐ Pattern Syntax
Extended Regex (-E, default)
Uses Python's re module (similar to grep -E):
# Multiple alternatives
earlyexit 'error|warning|fatal'
# Character classes
earlyexit '[Ee]rror'
# Quantifiers
earlyexit 'fail(ed|ure)?'
# Word boundaries
earlyexit '\berror\b'
Perl-Compatible Regex (-P)
Requires regex module (pip install earlyexit[perl]):
# Lookaheads/lookbehinds
earlyexit -P '(?<=ERROR: ).*'
# Named groups
earlyexit -P '(?P<level>ERROR|WARN): (?P<msg>.*)'
# Recursive patterns
earlyexit -P '\(((?:[^()]++|(?R))*+)\)'
๐ฏ Use Cases
1. Fast Feedback in CI/CD
Stop the build immediately on first error instead of waiting for full completion:
# GitLab CI example
script:
- make build 2>&1 | earlyexit -t 3600 'error' || exit 1
2. Cost Optimization
Save compute costs by stopping failed cloud operations early:
# Stop provisioning if errors detected in first 5 minutes
terraform apply | earlyexit -t 300 'Error:' && terraform destroy -auto-approve
3. Development Workflow
Get instant feedback during development:
# Watch for compilation errors
npm run watch | earlyexit 'ERROR'
4. Monitoring & Alerting
Detect issues in production logs:
# Alert on first critical error
kubectl logs -f pod-name | earlyexit 'CRITICAL' && send-alert
โก Performance Comparison
| Tool | Behavior | Time to Detect Error |
|---|---|---|
grep |
Processes entire input | After full completion |
grep -m 1 |
Stops after first match | Immediate (but no timeout) |
earlyexit |
Stops after first match + timeout | Immediate + safety net |
Real-World Example
# Command that takes 30 minutes but fails at 5 minutes
# grep: Waits full 30 minutes
command | grep 'Error' # 30 minutes wasted
# earlyexit: Exits at 5 minutes
command | earlyexit -t 1800 'Error' # Saves 25 minutes!
๐ง Integration with Other Tools
With tee (save logs + monitor)
command 2>&1 | stdbuf -o0 tee output.log | earlyexit -t 300 'Error'
With timeout (double safety)
timeout 600 bash << 'EOF'
command 2>&1 | stdbuf -o0 tee log.txt | earlyexit -t 300 'Error'
EOF
With stdbuf (unbuffered output)
command 2>&1 | stdbuf -o0 tee log.txt | earlyexit 'Error'
๐งช Testing
# Test success (no match)
echo "Starting..." | earlyexit 'Error' # Exit 1
# Test match (immediate exit)
echo "Error detected" | earlyexit 'Error' # Exit 0
# Test timeout
sleep 10 | earlyexit -t 2 'Error' # Exit 2 after 2 seconds
# Test case-insensitive
echo "ERROR" | earlyexit -i 'error' # Exit 0
# Test max count
printf "Error\nError\nError\n" | earlyexit -m 2 'Error' # Exit 0 after 2 matches
# Test invert match
echo "OK" | earlyexit -v 'Error' # Exit 1 (OK is not Error)
echo "Error" | earlyexit -v 'OK' # Exit 0 (Error doesn't match OK)
๐ Exit Codes
| Exit Code | Meaning | Use Case |
|---|---|---|
| 0 | Pattern matched | Error detected - fail fast |
| 1 | No match | Success - continue |
| 2 | Timeout | Command took too long |
| 3 | Error | Invalid pattern, broken pipe, etc. |
| 130 | Interrupted | Ctrl+C pressed |
๐ Comparison with grep
| Feature | grep | grep -m 1 | earlyexit |
|---|---|---|---|
| Pattern matching | โ | โ | โ |
| Extended regex | โ -E | โ -E | โ -E |
| Perl regex | โ -P | โ -P | โ -P (with regex module) |
| Stop on first match | โ | โ | โ |
| Timeout | โ | โ | โ -t |
| Exit code clarity | โ ๏ธ Complex | โ ๏ธ Complex | โ Simple (0/1/2/3) |
| Max count | โ | โ -m | โ -m |
| Invert match | โ -v | โ -v | โ -v |
| Color output | โ | โ | โ --color |
| Line numbers | โ -n | โ -n | โ -n |
๐ Troubleshooting
Pattern not matching?
# Test your pattern separately
echo "test string" | earlyexit 'pattern'
# Enable line numbers to see what's being processed
command | earlyexit -n 'pattern'
# Use -i for case-insensitive if needed
command | earlyexit -i 'pattern'
Timeout not working?
# Ensure timeout is numeric
earlyexit -t 10 'pattern' # โ
Correct
earlyexit -t 10s 'pattern' # โ Wrong - no 's' suffix
Buffering issues?
# Use stdbuf to disable buffering
command 2>&1 | stdbuf -o0 tee log.txt | earlyexit 'pattern'
๐ Best Practices
-
Always use timeout for long-running commands:
command | earlyexit -t 600 'Error' # โ Good command | earlyexit 'Error' # โ ๏ธ Risky - no timeout
-
Save logs with tee:
command 2>&1 | stdbuf -o0 tee log.txt | earlyexit -t 300 'Error'
-
Use case-insensitive for error detection:
earlyexit -i 'error' # Matches Error, ERROR, error
-
Multiple patterns with extended regex:
earlyexit -E '(error|warning|fatal|exception)'
-
Check exit codes properly:
command | earlyexit 'Error' case $? in 0) echo "Error detected"; exit 1 ;; 1) echo "Success" ;; 2) echo "Timeout"; exit 2 ;; *) echo "Unexpected error"; exit 3 ;; esac
๐ License
MIT License - see LICENSE file for details
๐ค Contributing
Contributions welcome! Please open an issue or PR on GitHub.
๐ Related Projects
- timeout - Command timeout utility (part of GNU coreutils)
- stdbuf - Modify buffering of streams (part of GNU coreutils)
- ripgrep (rg) - Fast grep alternative in Rust
๐ฎ Contact
Robert Lee - robert.lee@databricks.com
Made with โค๏ธ for developers who value fast feedback
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file earlyexit-0.0.1.tar.gz.
File metadata
- Download URL: earlyexit-0.0.1.tar.gz
- Upload date:
- Size: 11.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f420cf1017f40211301bd710fb7a6e565e4f4d556706e31a323393b65921fc5
|
|
| MD5 |
7e2355e92ab7de6ce40168cc3574828c
|
|
| BLAKE2b-256 |
04002648c1b00c27859043ae4baf403e926495d93da51d914dd81f20fc77418f
|
File details
Details for the file earlyexit-0.0.1-py3-none-any.whl.
File metadata
- Download URL: earlyexit-0.0.1-py3-none-any.whl
- Upload date:
- Size: 9.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cdffeb28eaf0404213d9b5daaf5543fed4450f9d7775725f30b825934076bf67
|
|
| MD5 |
3035a572d073feedf9af3ba9bcdce2a1
|
|
| BLAKE2b-256 |
0ae72d82da8e92dba27ed0a53c6d6d3d9fde1ca54d056689171c96874cbe276d
|