Flask非根路由无法被Apache服务:树莓派重启路由404问题求助
Hey there, let's work through why that restart route is throwing a 404 when accessing externally! The key clue here is that it works locally but not through Apache—this almost always boils down to a URL path mismatch between how Flask sees requests and how Apache forwards them.
Here's how to fix it, step by step:
1. Fix the Route Path Mismatch
When you run Flask directly (localhost:5000), your app handles requests starting from the root URL (/). But with your WSGI config, you’ve mapped the /sysinfo path to your Flask app—meaning Apache strips that /sysinfo prefix before passing the request to Flask.
Right now, your Flask route is defined as /sysinfo/restart_now, but when someone visits http://your-pi/sysinfo/restart_now, Apache sends the path /restart_now to Flask. Since Flask doesn’t have a route for /restart_now, it returns a 404.
Option A: Adjust the Flask Route (Quick Fix)
Update your route in index.py to remove the /sysinfo prefix:
@app.route("/restart_now", methods=['GET','POST']) def restart_now(): subprocess.call("delayed-reboot",shell=True) return render_template("restart_now.html")
Your existing form action (/sysinfo/restart_now) will still work perfectly: Apache forwards that request to Flask as /restart_now, which now matches your updated route.
Option B: Use Flask's APPLICATION_ROOT (Cleaner for Scaling)
If you want to keep your routes prefixed with /sysinfo (to avoid future conflicts), set the application root in index.py:
app.config['APPLICATION_ROOT'] = '/sysinfo'
Then, use Flask’s url_for helper in your template instead of hardcoding the URL—this ensures the form always points to the right path, even if your Apache config changes later:
<form action="{{ url_for('restart_now') }}" method="post"> <button name="restart_now" onclick="return confirm('Do you wish to shutdown your system ?')" class="button button-primary">Reboot Pi</button> </form>
2. Restart Apache to Apply Changes
After modifying your Flask code or config, always restart Apache to make sure the changes take effect:
sudo systemctl restart apache2
Even with WSGIScriptReloading On, manual restarts are the most reliable way to pick up route updates.
3. Check Apache's Error Log for Clues
If the 404 persists, dig into your error log to confirm what’s happening:
cat /var/www/sysinfo/logs/error.log
You’ll likely see entries showing the exact path being sent to Flask, which can confirm the mismatch we talked about.
Bonus: Fix Sudo Permissions for Reboot
Once you fix the 404, you might hit another issue: the www-data user (which Apache runs as) probably doesn’t have permission to run sudo reboot. To fix this:
- Edit the sudoers file (use
visudoto avoid syntax errors):sudo visudo - Add this line at the end to let
www-datarunrebootwithout a password:www-data ALL=(ALL) NOPASSWD: /sbin/reboot - Save and exit (for nano: Ctrl+O, press Enter, then Ctrl+X).
This will ensure your delayed-reboot script executes successfully when triggered.
内容的提问来源于stack exchange,提问作者Dizzixx

