diff --git a/ipk-source/sdxpinn-quecmanager-beta/root/www/cgi-bin/quecmanager/home/speedtest/speedtest_status.sh b/ipk-source/sdxpinn-quecmanager-beta/root/www/cgi-bin/quecmanager/home/speedtest/speedtest_status.sh index 153996d..a5eff06 100755 --- a/ipk-source/sdxpinn-quecmanager-beta/root/www/cgi-bin/quecmanager/home/speedtest/speedtest_status.sh +++ b/ipk-source/sdxpinn-quecmanager-beta/root/www/cgi-bin/quecmanager/home/speedtest/speedtest_status.sh @@ -1,29 +1,71 @@ #!/bin/sh # Location: /www/cgi-bin/quecmanager/home/speedtest/speedtest_status.sh +# Configuration STATUS_FILE="/tmp/speedtest_status.json" FINAL_RESULT="/tmp/speedtest_final.json" +PID_FILE="/tmp/speedtest.pid" +# Set headers echo "Content-Type: application/json" echo "Cache-Control: no-cache, no-store, must-revalidate" echo "Pragma: no-cache" echo "Expires: 0" echo "" -# Check if the test is completed and we have a final result -if [ -f "$FINAL_RESULT" ] && [ -r "$FINAL_RESULT" ] && [ -s "$FINAL_RESULT" ]; then - # Return the saved final result - cat $FINAL_RESULT -elif [ -f "$STATUS_FILE" ]; then - # Check if the file is readable and not empty - if [ -r "$STATUS_FILE" ] && [ -s "$STATUS_FILE" ]; then - # Return current status if test is running - cat $STATUS_FILE - else - # File exists but is empty or not readable - echo '{"status": "pending", "message": "Test initializing..."}' +# Function to return file content if it's a valid result +return_if_result() { + local file="$1" + if [ -f "$file" ] && [ -r "$file" ] && [ -s "$file" ]; then + if grep -q '"type":"result"' "$file" 2>/dev/null; then + cat "$file" + return 0 + fi fi -else - # Indicate no active test - echo '{"status": "not_running"}' -fi \ No newline at end of file + return 1 +} + +# Function to check if process is running +is_process_running() { + if [ -f "$PID_FILE" ]; then + PID=$(cat "$PID_FILE" 2>/dev/null) + if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then + return 0 + fi + fi + return 1 +} + +# Priority 1: Check FINAL_RESULT file first +if return_if_result "$FINAL_RESULT"; then + exit 0 +fi + +# Priority 2: Check STATUS_FILE for completed result +if return_if_result "$STATUS_FILE"; then + # Copy to final result for future requests + cp "$STATUS_FILE" "$FINAL_RESULT" 2>/dev/null + chmod 644 "$FINAL_RESULT" 2>/dev/null + exit 0 +fi + +# Priority 3: If process is running, return current status +if is_process_running; then + if [ -f "$STATUS_FILE" ] && [ -r "$STATUS_FILE" ] && [ -s "$STATUS_FILE" ]; then + cat "$STATUS_FILE" + else + echo '{"status":"running","message":"Test in progress...","timestamp":'$(date +%s)'}' + fi + exit 0 +fi + +# Priority 4: Check for error status +if [ -f "$STATUS_FILE" ] && [ -r "$STATUS_FILE" ] && [ -s "$STATUS_FILE" ]; then + if grep -q '"status":"error"' "$STATUS_FILE" 2>/dev/null; then + cat "$STATUS_FILE" + exit 0 + fi +fi + +# Default: No test running +echo '{"status":"not_running","timestamp":'$(date +%s)'}' \ No newline at end of file diff --git a/ipk-source/sdxpinn-quecmanager-beta/root/www/cgi-bin/quecmanager/home/speedtest/start_speedtest.sh b/ipk-source/sdxpinn-quecmanager-beta/root/www/cgi-bin/quecmanager/home/speedtest/start_speedtest.sh index 8d376e2..a80b786 100755 --- a/ipk-source/sdxpinn-quecmanager-beta/root/www/cgi-bin/quecmanager/home/speedtest/start_speedtest.sh +++ b/ipk-source/sdxpinn-quecmanager-beta/root/www/cgi-bin/quecmanager/home/speedtest/start_speedtest.sh @@ -1,36 +1,118 @@ #!/bin/sh # Location: /www/cgi-bin/quecmanager/home/speedtest/start_speedtest.sh +# Configuration STATUS_FILE="/tmp/speedtest_status.json" FINAL_RESULT="/tmp/speedtest_final.json" +PID_FILE="/tmp/speedtest.pid" +LOG_FILE="/tmp/speedtest.log" +TIMEOUT=300 # 5 minutes timeout # Set content type header echo "Content-Type: application/json" echo "" -# Remove any existing status files -rm -f $STATUS_FILE -rm -f $FINAL_RESULT +# Function to cleanup on exit +cleanup() { + if [ -f "$PID_FILE" ]; then + PID=$(cat "$PID_FILE" 2>/dev/null) + if [ -n "$PID" ]; then + kill "$PID" 2>/dev/null + wait "$PID" 2>/dev/null + fi + rm -f "$PID_FILE" + fi + rm -f "$STATUS_FILE" +} + +# Check if speedtest is already running +if [ -f "$PID_FILE" ]; then + PID=$(cat "$PID_FILE" 2>/dev/null) + if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then + echo '{"status":"error","message":"Speedtest already running"}' + exit 1 + fi + # Clean up stale PID file + rm -f "$PID_FILE" +fi + +# Remove any existing files +rm -f "$STATUS_FILE" "$FINAL_RESULT" "$LOG_FILE" + +# Check if speedtest binary exists +if ! command -v speedtest >/dev/null 2>&1; then + echo '{"status":"error","message":"Speedtest binary not found"}' + exit 1 +fi + +# Create directories if they don't exist +mkdir -p /tmp/home 2>/dev/null # Initialize status file -echo '{"status": "starting"}' > $STATUS_FILE -chmod 644 $STATUS_FILE +echo '{"status":"starting","timestamp":'$(date +%s)'}' > "$STATUS_FILE" +chmod 644 "$STATUS_FILE" -# Run speedtest in background and pipe output to status file +# Start speedtest in background with proper error handling ( + # Set environment export HOME=/tmp/home - /usr/bin/speedtest --accept-license -f json -p yes --progress-update-interval=100 | \ + export PATH="/usr/bin:/bin:/usr/sbin:/sbin" + + # Log start time + echo "Starting speedtest at $(date)" > "$LOG_FILE" + + # Run speedtest with timeout and error handling + timeout "$TIMEOUT" speedtest --accept-license --format=json --progress=yes --progress-update-interval=500ms 2>>"$LOG_FILE" | \ while IFS= read -r line; do - # Update status file with latest JSON data - echo "$line" > $STATUS_FILE - - # If this is a result line, also save it as the final result - if echo "$line" | grep -q '"type":"result"'; then - echo "$line" > $FINAL_RESULT - chmod 644 $FINAL_RESULT + # Validate JSON before writing + if echo "$line" | grep -q '^{.*}$'; then + # Write the line as-is (speedtest already includes timestamp) + echo "$line" > "$STATUS_FILE" + + # Check if this is the final result + if echo "$line" | grep -q '"type":"result"'; then + echo "$line" > "$FINAL_RESULT" + chmod 644 "$FINAL_RESULT" + echo "Speedtest completed at $(date)" >> "$LOG_FILE" + echo "Final result written to $FINAL_RESULT" >> "$LOG_FILE" + break + fi + else + # Log non-JSON output + echo "Non-JSON output: $line" >> "$LOG_FILE" fi done + + # Check if we have a result after the loop + if [ ! -f "$FINAL_RESULT" ] && [ -f "$STATUS_FILE" ]; then + # Check if the last status was actually a result + if grep -q '"type":"result"' "$STATUS_FILE" 2>/dev/null; then + cp "$STATUS_FILE" "$FINAL_RESULT" + chmod 644 "$FINAL_RESULT" + echo "Copied result from status file to final result" >> "$LOG_FILE" + fi + fi + + # Handle timeout or error cases + if [ $? -ne 0 ]; then + ERROR_MSG="Speedtest failed or timed out" + echo "Error: $ERROR_MSG at $(date)" >> "$LOG_FILE" + echo "{\"status\":\"error\",\"message\":\"$ERROR_MSG\",\"timestamp\":$(date +%s)}" > "$STATUS_FILE" + fi + + # Keep PID file for a moment to let status script detect completion + sleep 2 + + # Cleanup PID file + rm -f "$PID_FILE" + ) & +# Save the background process PID +echo $! > "$PID_FILE" + +# Set up cleanup trap +trap cleanup EXIT INT TERM + # Return immediate success response -echo '{"status":"started"}' \ No newline at end of file +echo '{"status":"started","timestamp":'$(date +%s)'}' \ No newline at end of file