You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Node.js的python-shell心跳监控实现方案问询

Got it, let’s walk through how to implement heartbeat monitoring for your long-running Python scripts (executed via python-shell) and display their active/inactive status in an HTML table. I’ve built similar setups before, so here’s a practical, step-by-step approach:

1. Implement Heartbeat Signals in Python Scripts

First, modify your persistent Python scripts to send regular heartbeat messages to Node.js. We’ll use stdout to send a uniquely formatted signal that Node.js can easily identify.

import time
import sys
import threading

def send_heartbeat():
    # Send a heartbeat every 10 seconds (adjust interval as needed)
    while True:
        print("HEARTBEAT:ACTIVE", flush=True)  # Flush ensures immediate delivery
        time.sleep(10)

# Start heartbeat as a daemon thread (dies when main script exits)
heartbeat_thread = threading.Thread(target=send_heartbeat, daemon=True)
heartbeat_thread.start()

# Your existing script logic goes here...

2. Track Script Status in Node.js

Create a state store to track each running script’s heartbeat timestamp and current status. Use python-shell event listeners to update this state when heartbeats are received, or when the script exits/errors.

const { PythonShell } = require('python-shell');
const scriptStatuses = new Map(); // Key: unique script ID, Value: status object

function startMonitoredScript(scriptId, scriptPath, options = {}) {
    const initialHeartbeat = Date.now();
    scriptStatuses.set(scriptId, {
        lastHeartbeat: initialHeartbeat,
        status: 'active',
        shellInstance: null
    });

    const shell = new PythonShell(scriptPath, options);
    scriptStatuses.get(scriptId).shellInstance = shell;

    // Listen for heartbeat messages
    shell.on('message', (message) => {
        if (message.trim() === 'HEARTBEAT:ACTIVE') {
            const status = scriptStatuses.get(scriptId);
            status.lastHeartbeat = Date.now();
            status.status = 'active';
        }
    });

    // Handle script exit/error
    shell.on('close', (exitCode) => {
        scriptStatuses.get(scriptId).status = 'inactive';
        console.log(`Script ${scriptId} exited with code ${exitCode}`);
    });

    shell.on('error', (err) => {
        scriptStatuses.get(scriptId).status = 'inactive';
        console.error(`Script ${scriptId} encountered an error:`, err);
    });
}

// Example: Start a script with ID "data-processor"
startMonitoredScript("data-processor", "./scripts/data-processor.py");

3. Add Heartbeat Timeout Checks

Set up a recurring check to mark scripts as inactive if they stop sending heartbeats for longer than a threshold (give a small buffer over your Python heartbeat interval).

const HEARTBEAT_TIMEOUT = 20000; // 20 seconds (longer than Python's 10s interval)

// Check status every 15 seconds
setInterval(() => {
    const currentTime = Date.now();
    scriptStatuses.forEach((status, scriptId) => {
        if (currentTime - status.lastHeartbeat > HEARTBEAT_TIMEOUT) {
            status.status = 'inactive';
            // Optional: Auto-restart the script if needed
            // restartScript(scriptId);
        }
    });
}, 15000);

4. Expose a Status API for the Frontend

Use a framework like Express to create an endpoint that returns the current script statuses to your HTML page.

const express = require('express');
const app = express();
const port = 3000;

// Serve your HTML file
app.use(express.static('public'));

// API endpoint to get script statuses
app.get('/api/script-statuses', (req, res) => {
    const statusList = Array.from(scriptStatuses.entries()).map(([id, status]) => ({
        scriptId: id,
        status: status.status,
        lastHeartbeat: new Date(status.lastHeartbeat).toLocaleString()
    }));
    res.json(statusList);
});

app.listen(port, () => {
    console.log(`Monitor server running on http://localhost:${port}`);
});

5. Build the HTML Status Table

Create an HTML page that fetches status data periodically and updates the table dynamically.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Python Script Monitor</title>
    <style>
        table { border-collapse: collapse; width: 80%; margin: 2rem auto; }
        th, td { border: 1px solid #ddd; padding: 0.8rem; text-align: left; }
        th { background-color: #f5f5f5; }
        .active { color: #2ecc71; font-weight: bold; }
        .inactive { color: #e74c3c; font-weight: bold; }
    </style>
</head>
<body>
    <h1 style="text-align: center;">Python Script Status Monitor</h1>
    <table id="statusTable">
        <thead>
            <tr>
                <th>Script ID</th>
                <th>Status</th>
                <th>Last Heartbeat</th>
            </tr>
        </thead>
        <tbody></tbody>
    </table>

    <script>
        function updateStatusTable() {
            fetch('/api/script-statuses')
                .then(res => res.json())
                .then(statuses => {
                    const tbody = document.querySelector('#statusTable tbody');
                    tbody.innerHTML = '';
                    
                    statuses.forEach(script => {
                        const row = document.createElement('tr');
                        row.innerHTML = `
                            <td>${script.scriptId}</td>
                            <td class="${script.status}">${script.status.toUpperCase()}</td>
                            <td>${script.lastHeartbeat}</td>
                        `;
                        tbody.appendChild(row);
                    });
                })
                .catch(err => console.error('Failed to load statuses:', err));
        }

        // Update table every 10 seconds
        setInterval(updateStatusTable, 10000);
        // Load initial status on page load
        updateStatusTable();
    </script>
</body>
</html>

Bonus: Real-Time Updates with WebSockets

For more immediate status updates (instead of polling), use Socket.io to push status changes to the frontend automatically:

  1. Add Socket.io to your Node.js server
  2. Emit a status-update event whenever a script’s status changes
  3. Modify the frontend to listen for these events and update the table instantly

内容的提问来源于stack exchange,提问作者Harsh Goyal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:53:55