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

如何在Node中用python_shell重定向Bokeh Server日志至文件?

How to Redirect Bokeh Server Logs to a File in Real-Time with python_shell in Node.js

Let's break down why your initial approach didn't work, then walk through two solid solutions—one using shell redirection with python_shell, and a more robust stream-based method that eliminates the zombie process issue you faced with exec.

Why Your First Attempt Failed

The >> and 2>&1 are shell redirection operators, not arguments for the Python interpreter or Bokeh Server. When you passed them in args or pythonOptions, python_shell treated them as literal command-line inputs for bokeh serve, which is why they had no effect. By default, python_shell runs the Python process directly, not through a shell, so shell-specific syntax isn't parsed.

Solution 1: Enable Shell Mode in python_shell

If you prefer to use shell redirection, you can tell python_shell to execute the command through a shell. This lets the shell handle the log redirection operators properly.

Here's the adjusted code:

const PythonShell = require('python-shell').PythonShell;

// Build the full shell command (wrap paths in quotes if they contain spaces)
const fullCommand = `${python_path} -m bokeh serve >> ${debug_path} 2>&1`;

const options = {
  shell: true, // Enable shell execution to parse redirection operators
  cwd: `${path}` // Set the working directory where Bokeh should run
};

PythonShell.run(fullCommand, options, (err, results) => {
  if (err) {
    logger.error(`${err}`);
    return;
  }
  if (results) {
    logger.info(results);
  }
});

Note: If your paths (like python_path or debug_path) include spaces, wrap them in double quotes to avoid shell parsing errors, e.g., "${python_path}".

This method avoids shell dependencies entirely. Instead, we'll listen to the stdout/stderr streams from the Bokeh Server process and write logs to the file in real-time. Most importantly, we can properly clean up the child process if Node is terminated, fixing the zombie process problem from your exec approach.

Here's the implementation:

const fs = require('fs');
const PythonShell = require('python-shell').PythonShell;

// Create a write stream for the log file (append mode to preserve existing logs)
const logStream = fs.createWriteStream(debug_path, { flags: 'a' });

// Set the working directory for Bokeh Server
process.chdir(`${path}`);

const options = {
  pythonPath: `${python_path}`,
  pythonOptions: ['-m', 'bokeh', 'serve']
};

// Initialize the PythonShell instance
const bokehProcess = new PythonShell('', options);

// Capture stdout and write to log file in real-time
bokehProcess.stdout.on('data', (data) => {
  const output = data.toString().trim();
  logStream.write(`${output}\n`); // Add newline for readable log formatting
  logger.info(output); // Optional: also log to Node's internal logger
});

// Capture stderr and write to log file (mark errors explicitly)
bokehProcess.stderr.on('data', (data) => {
  const errorOutput = data.toString().trim();
  logStream.write(`[ERROR] ${errorOutput}\n`);
  logger.error(errorOutput);
});

// Clean up when Bokeh Server exits
bokehProcess.end((err) => {
  if (err) {
    logger.error(`Bokeh Server error: ${err}`);
  }
  logStream.end(); // Close the log stream to avoid resource leaks
  logger.info('Bokeh Server process exited cleanly');
});

// Prevent zombie processes by killing Bokeh when Node receives termination signals
process.on('SIGINT', () => {
  bokehProcess.childProcess.kill();
  logStream.end();
  logger.info('Node process interrupted; Bokeh Server terminated');
  process.exit(0);
});

process.on('SIGTERM', () => {
  bokehProcess.childProcess.kill();
  logStream.end();
  logger.info('Node process terminated; Bokeh Server terminated');
  process.exit(0);
});

Why This Is Better:

  • No shell dependency: Avoids path escaping issues and shell-specific behavior.
  • Real-time control: You can filter, format, or modify logs before writing them to the file.
  • Zombie process prevention: We explicitly kill the Bokeh Server when Node receives termination signals (like SIGINT for Ctrl+C or SIGTERM for graceful shutdown), ensuring no orphaned processes are left behind.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:45:49