How to Debug CAPEv2 Service Failures: A Complete Guide to System Log Analysis and Troubleshooting
Use systemctl status and journalctl to inspect systemd-level failures, then examine application logs in /opt/CAPEv2/log/ and per-analysis logs in storage/analyses/<id>/ to trace root causes.
CAPEv2 malware analysis framework runs as a collection of systemd services that can fail silently or crash unexpectedly. Understanding how to debug CAPEv2 service failures requires tracing issues through three architectural layers: the systemd unit definitions, the Python bootstrap process in cuckoo.py, and the application's logging infrastructure in utils/process.py. This guide maps the exact file paths and commands needed to diagnose crashes, permission errors, and processing bottlenecks.
Systemd-Level Diagnostics
CAPEv2 services like cape.service, cape-processor.service, and cape-rooter.service are controlled by systemd unit files located in the repository's systemd/ directory. When a service stops unexpectedly, start your investigation at the init system layer.
Check Service Status and Exit Codes
Run systemctl to view the current state, restart count, and recent journal entries:
systemctl status cape.service
This command reveals the exit code and whether systemd has triggered the Restart=always policy defined in systemd/cape.service.
Inspect the System Journal
To view the complete boot log for the service without pagination:
journalctl -u cape.service -b --no-pager
The -b flag limits output to the current boot, which isolates logs after a recent system restart or crash.
Enable Debug Mode at the Service Level
Force the service to run with verbose logging by setting an environment variable in the systemd unit. Edit /etc/systemd/system/cape.service or the repository's systemd/cape.service to add:
Environment=CAPEv2_DEBUG=1
StandardOutput=journal
StandardError=journal
Then reload and restart:
systemctl daemon-reload
systemctl restart cape.service
This configuration ensures that cuckoo.py receives the debug flag, causing init_logging to set log.setLevel(logging.DEBUG) as implemented in lines 75-78 of cuckoo.py.
Application-Level Logging Architecture
Once past the systemd layer, CAPEv2 uses Python's standard logging module with configurations defined in two critical files.
Global Logger Configuration
The Django web interface defines its logging behavior in web/web/settings.py (lines 79-99). This LOGGING dictionary controls whether HTTP 500 errors trigger admin emails. Note that the mail handler disables automatically when DEBUG=True, so production troubleshooting requires DEBUG=False in this file to receive crash notifications.
Rotating File Handlers
The utils/process.py file contains the init_logging function that builds three handlers: a console handler, an optional syslog handler, and a rotating file handler. By default, this writes to <CUCKOO_ROOT>/log/process.log with rotation logic around lines 11-15 of the function.
When you run cuckoo.py with the -d flag, the bootstrap script calls init_logging with debug=True, which sets the log level to DEBUG at lines 23-26 of init_logging.
Real-Time Log Monitoring
Monitor the central application log during service startup:
tail -f /opt/CAPEv2/log/process.log | grep -i "error"
Per-Analysis Log Files
Each analysis task generates isolated logs through init_per_analysis_logging in utils/process.py (lines 32-48). These files follow the naming convention process-<task_id>.log and reside in one of two locations depending on your configuration:
- Centralized:
/opt/CAPEv2/log/process-<task_id>.log - Analysis-specific:
/opt/CAPEv2/storage/analyses/<task_id>/process.log
The location is controlled by the logconf.logger.process_analysis_folder configuration flag.
To inspect a specific failed analysis:
TASK_ID=1234
LOG_PATH="/opt/CAPEv2/storage/analyses/${TASK_ID}/process.log"
if [ -f "$LOG_PATH" ]; then
less "$LOG_PATH"
else
echo "No per-analysis log - checking central log"
less "/opt/CAPEv2/log/process.log"
fi
Common Failure Patterns and Diagnostic Signals
| Symptom | Root Cause | Diagnostic Location |
|---|---|---|
| Service repeatedly restarts every 5 minutes | Systemd RestartSec=5m policy triggered by PermissionError in init_logging (lines 20-21) |
journalctl -u cape.service for permission denials on /opt/CAPEv2/log/ |
| Missing analysis results | init_per_analysis_logging fails to create log files due to missing directories or permissions |
utils/process.py lines 54-56 for PermissionError exceptions |
| No HTTP 500 email alerts | Django LOGGING dict disables admin mailer when DEBUG=True in web/web/settings.py |
Verify DEBUG=False and mail server configuration |
| Stuck processing pool | Unhandled exception in processing_finished |
Look for log.exception tracebacks at line 91 in process logs |
| Tcpdump permission errors | check_tcpdump_permissions failure during cuckoo_init |
Early boot logs in cuckoo.py around line 88 |
Manual Debugging Commands
When automated service restarts obscure the error, run CAPEv2 manually to capture full debug output:
cd /opt/CAPEv2
python -d cuckoo.py -m 10
The -d flag forces debug logging directly to your terminal, bypassing the systemd journal. This is particularly effective for catching import errors or database connection failures during the bootstrap phase in cuckoo.py.
For router-related service issues, examine utils/router_manager.py for additional CLI debug flags that control network routing diagnostics.
Summary
- Systemd layer: Use
systemctl status cape.serviceandjournalctl -u cape.service -bto identify crash loops and exit codes. - Bootstrap layer: Run
python -d cuckoo.pymanually to expose debug output fromcuckoo_initbefore the daemon forks. - Application layer: Check rotating logs in
/opt/CAPEv2/log/process.logconfigured byutils/process.py. - Task layer: Inspect per-analysis logs in
storage/analyses/<task_id>/process.loggenerated byinit_per_analysis_logging. - Permissions: Ensure the
capeuser owns thelog/directory (chmod 750) and all parent paths are writable.
Frequently Asked Questions
Why does my CAPEv2 service keep restarting every 5 minutes?
Systemd's Restart=always policy in systemd/cape.service triggers this behavior when the Python process exits with an error. Check journalctl -u cape.service for PermissionError messages from init_logging (lines 20-21 of utils/process.py), which typically indicate the cape user cannot write to /opt/CAPEv2/log/ or create the per-analysis log directories.
How do I enable debug logging for a single analysis without changing the global service configuration?
Run the processing component manually with the debug flag: python -d utils/process.py <task_id>. This invokes init_logging with debug=True, setting log.setLevel(logging.DEBUG) and creating verbose output in either the central log or the specific analysis folder depending on your logconf.logger.process_analysis_folder setting.
Where are HTTP 500 errors logged when the web interface crashes?
The Django logging configuration in web/web/settings.py (lines 79-99) controls this behavior. By default, HTTP 500 errors trigger admin emails only when DEBUG=False. If DEBUG=True in your configuration, errors appear only in the console or web.log file without email alerts. Check the LOGGING dictionary's admin email handler configuration to ensure SMTP settings are correct.
What causes "Permission denied" errors for tcpdump during CAPEv2 startup?
The check_tcpdump_permissions function called during cuckoo_init (around line 88 of cuckoo.py) validates that the cape user can execute tcpdump. These errors appear early in the boot log. Ensure the cape user is a member of the wireshark or pcap group, or that tcpdump has the appropriate capabilities set via setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →