Skip to content

Commit 61cefb1

Browse files
Copilotc4g7-dev
andcommitted
Improve Linux installation: better error handling and logging
- Add Linux-specific error handling (errno 98, 13) for port binding - Improve logging for internal speedtest server startup - Improve logging for scheduler initialization - Add scheduler section to default config.yaml - Add port 5201 availability check in install script - Enhance installation script output with better diagnostics - Add explicit permission settings for data/logs directories Co-authored-by: c4g7-dev <141867000+c4g7-dev@users.noreply.github.com>
1 parent 3e052e6 commit 61cefb1

File tree

5 files changed

+82
-16
lines changed

5 files changed

+82
-16
lines changed

app/internal_speedtest.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,11 @@ def start(self) -> bool:
207207
return True
208208

209209
except OSError as e:
210-
if e.errno == 10048: # Windows: Address already in use
210+
import errno
211+
if e.errno in (10048, errno.EADDRINUSE): # Windows: 10048, Linux: 98
211212
LOGGER.error(f"Port {self.port} is already in use")
213+
elif e.errno == errno.EACCES: # Permission denied (Linux)
214+
LOGGER.error(f"Permission denied when trying to bind to port {self.port}")
212215
else:
213216
LOGGER.error(f"Failed to start server: {e}")
214217
self._server_socket = None

app/scheduler.py

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def __init__(
3535
def _load_scheduler_config(self) -> dict:
3636
"""Load scheduler configuration from JSON file."""
3737
if not self.config_file.exists():
38+
LOGGER.debug("Scheduler config file not found at %s, using defaults", self.config_file)
3839
return {
3940
"mode": "simple",
4041
"enabled": self.config.scheduler.enabled,
@@ -43,9 +44,22 @@ def _load_scheduler_config(self) -> dict:
4344

4445
try:
4546
with open(self.config_file, "r") as f:
46-
return json.load(f)
47+
config = json.load(f)
48+
LOGGER.debug("Loaded scheduler config from %s: mode=%s",
49+
self.config_file, config.get("mode", "simple"))
50+
return config
51+
except PermissionError as exc:
52+
LOGGER.error("Permission denied reading scheduler config from %s: %s",
53+
self.config_file, exc)
54+
LOGGER.error("Using default configuration. Check file permissions.")
55+
return {
56+
"mode": "simple",
57+
"enabled": self.config.scheduler.enabled,
58+
"interval": self.config.scheduler.interval_minutes
59+
}
4760
except Exception as exc:
48-
LOGGER.error("Failed to load scheduler config: %s", exc)
61+
LOGGER.error("Failed to load scheduler config from %s: %s",
62+
self.config_file, exc, exc_info=True)
4963
return {
5064
"mode": "simple",
5165
"enabled": self.config.scheduler.enabled,
@@ -127,25 +141,33 @@ def _get_interval_minutes(self, sched_config: dict) -> int:
127141

128142
def start(self) -> None:
129143
if self.started:
144+
LOGGER.warning("Scheduler already started, ignoring duplicate start request")
130145
return
131146

147+
LOGGER.info("Initializing scheduler...")
132148
sched_config = self._load_scheduler_config()
133149

134150
# Check if scheduler is enabled (for simple mode)
135151
if sched_config.get("mode") == "simple" and not sched_config.get("enabled", True):
136-
LOGGER.info("Scheduler is disabled in configuration")
152+
LOGGER.warning("Scheduler is disabled in configuration (simple mode)")
153+
LOGGER.info("To enable scheduler, go to the dashboard and toggle the scheduler on")
137154
return
138155

139-
interval = self._get_interval_minutes(sched_config)
140-
trigger = IntervalTrigger(minutes=interval)
141-
self.scheduler.add_job(self._run_cycle, trigger=trigger, id="scheduled-measurements")
142-
self.scheduler.start()
143-
self.started = True
144-
LOGGER.info(
145-
"Scheduler started with interval %s minutes (mode: %s)",
146-
interval,
147-
sched_config.get("mode", "simple")
148-
)
156+
try:
157+
interval = self._get_interval_minutes(sched_config)
158+
trigger = IntervalTrigger(minutes=interval)
159+
self.scheduler.add_job(self._run_cycle, trigger=trigger, id="scheduled-measurements")
160+
self.scheduler.start()
161+
self.started = True
162+
LOGGER.info(
163+
"✓ Scheduler started successfully with interval %s minutes (mode: %s)",
164+
interval,
165+
sched_config.get("mode", "simple")
166+
)
167+
except Exception as exc:
168+
LOGGER.error("✗ Failed to start scheduler: %s", exc, exc_info=True)
169+
LOGGER.error(" Scheduled measurements will not run automatically")
170+
LOGGER.error(" You can still trigger measurements manually from the dashboard")
149171

150172
def shutdown(self) -> None:
151173
if self.started:

app/web/app.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,15 @@ def create_web_app(
4949
internal_exporter = InternalCSVExporter(internal_session_factory, data_dir)
5050

5151
# Auto-start the speedtest server on app startup
52+
LOGGER.info("Starting internal speedtest server...")
5253
if internal_manager.start_server():
53-
LOGGER.info("Internal speedtest server started automatically on startup")
54+
LOGGER.info("Internal speedtest server started successfully on port 5201")
5455
else:
55-
LOGGER.warning("Failed to auto-start internal speedtest server")
56+
LOGGER.error("✗ Failed to start internal speedtest server - check logs for details")
57+
LOGGER.error(" The homenet speedtest feature will not be available")
58+
LOGGER.error(" Common issues:")
59+
LOGGER.error(" - Port 5201 already in use by another service")
60+
LOGGER.error(" - Permission denied (check systemd service configuration)")
5661

5762
@app.route("/")
5863
def index():

config.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ bufferbloat:
3030
ping_host: 1.1.1.1
3131
ping_count: 20
3232

33+
scheduler:
34+
enabled: true
35+
interval_minutes: 30
36+
3337
web:
3438
host: 0.0.0.0
3539
port: 8000

install-linux.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,12 @@ mkdir -p "$INSTALL_DIR"/{data,logs,bin}
7171
# Copy application files
7272
echo "Copying application files..."
7373
cp -r . "$INSTALL_DIR/"
74+
75+
# Set proper ownership
7476
chown -R "$SERVICE_USER:$SERVICE_USER" "$INSTALL_DIR"
77+
# Ensure data directory is writable
78+
chmod 755 "$INSTALL_DIR/data"
79+
chmod 755 "$INSTALL_DIR/logs"
7580
echo -e "${GREEN}✓ Files copied to $INSTALL_DIR${NC}\n"
7681

7782
# Create virtual environment
@@ -91,6 +96,17 @@ echo "Downloading Ookla Speedtest CLI..."
9196
sudo -u "$SERVICE_USER" .venv/bin/python installer.py
9297
echo -e "${GREEN}✓ Ookla binary downloaded${NC}\n"
9398

99+
# Check if port 5201 is available for internal speedtest server
100+
echo "Checking if port 5201 is available for internal speedtest server..."
101+
if lsof -Pi :5201 -sTCP:LISTEN -t >/dev/null 2>&1 || netstat -tuln 2>/dev/null | grep -q ":5201 "; then
102+
echo -e "${YELLOW}⚠ Warning: Port 5201 is already in use${NC}"
103+
echo -e "${YELLOW} The internal homenet speedtest feature may not work${NC}"
104+
echo -e "${YELLOW} You can check what's using it with: sudo lsof -i :5201${NC}"
105+
else
106+
echo -e "${GREEN}✓ Port 5201 is available${NC}"
107+
fi
108+
echo ""
109+
94110
# Install systemd service
95111
echo "Installing systemd service..."
96112
cp netwatch.service "$SERVICE_FILE"
@@ -115,6 +131,12 @@ fi
115131
echo -e "${GREEN}=== Installation Complete! ===${NC}\n"
116132
echo "NetWatch is now running as a systemd service"
117133
echo ""
134+
echo "Features enabled:"
135+
echo " ✓ Internet speedtest (Ookla)"
136+
echo " ✓ Internet bufferbloat testing (iperf3)"
137+
echo " ✓ Homenet speedtest server (port 5201)"
138+
echo " ✓ Automatic scheduler (check dashboard to configure)"
139+
echo ""
118140
echo "Useful commands:"
119141
echo " - View status: systemctl status netwatch"
120142
echo " - View logs: journalctl -u netwatch -f"
@@ -125,3 +147,13 @@ echo ""
125147
echo "Dashboard URL: http://$(hostname -I | awk '{print $1}'):8000"
126148
echo ""
127149
echo -e "${YELLOW}Note: Make sure port 8000 is open in your firewall${NC}"
150+
echo -e "${YELLOW} For homenet speedtest, port 5201 should also be accessible on your LAN${NC}"
151+
echo ""
152+
echo "To verify everything is working:"
153+
echo " 1. Open the dashboard in your browser"
154+
echo " 2. Check the scheduler status in the top right"
155+
echo " 3. Try a manual speedtest"
156+
echo " 4. Check the Homenet tab to verify internal speedtest server is running"
157+
echo ""
158+
echo "If you encounter issues, check the logs with:"
159+
echo " journalctl -u netwatch -n 100 --no-pager"

0 commit comments

Comments
 (0)