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

NodeJS迁移函数中child_process spawn调用ENOENT错误排查求助

问题描述

我尝试复刻一个代码库中的migrate函数,改用Node.js(而非TypeScript)开发,大部分配置已完成,但运行迁移函数时,child_process.spawn调用自定义的node-pg-migrate文件出现ENOENT错误,提示找不到该文件。

相关代码

migrate.js

import { spawn } from 'child_process';
import * as path from 'path';
import dotenv from 'dotenv';
import * as url from 'node:url';

dotenv.config();

const __dirname = url.fileURLToPath(new URL('.', import.meta.url));

export function migrate(commandArguments, migrationsDir = __dirname)
{
    const spawnArgs = ['--migrations-dir', migrationsDir, ...commandArguments];
    console.log('Running command:');
    console.dir(`node-pg-migrate ${spawnArgs.join(' ')}`);
    console.log(`Spawn Path: \n${path.resolve(migrationsDir, 'node-pg-migrate')}\n`);
    const child = spawn(
        path.resolve(migrationsDir, 'node-pg-migrate'),
        spawnArgs,
        { env: { ...process.env }, windowsVerbatimArguments: false }
    );
    child.on('error', function (error) { console.log(error.message); });
    child.stdout.on('data', function (data) { console.log('stdout output: '); console.log(data.toString()); });
    child.stderr.on('data', function (data) { console.log('stderr output: '); console.log(data.toString()); });
    child.on('close', (code, signal) => { console.log(`child process exited with code: ${code} and signal: ${signal}`); });
    return child;
}
//ES6 Main Check
if (import.meta.url.startsWith('file:')) {
    const modulePath = url.fileURLToPath(import.meta.url);
    if (process.argv[1] === modulePath) {
        migrate(process.argv.slice(2), path.resolve(__dirname, '../migrations'));
    }
}

自定义node-pg-migrate文件

#!usr/bin/env node
require('../config/nodeconfig.json')
require('../node_modules/node-pg-migrate/bin/node-pg-migrate')

执行输出

在PowerShell中执行npm run migrate up,输出如下:

npm WARN config global --global, --local are deprecated. Use --location=global instead.

desktop-server@1.0.0 migrate
node ./migrations/migrate.js "up"

Running command: 'node-pg-migrate --migrations-dir C:\Users\M\NodeJSProjects\xxxx\Prototype2\desktop-server\migrations up'
Spawn Path:
C:\Users\M\NodeJSProjects\xxxx\Prototype2\desktop-server\migrations\node-pg-migrate
spawn C:\Users\M\NodeJSProjects\xxxx\Prototype2\desktop-server\migrations\node-pg-migrate ENOENT child process exited with code: -4058 and signal: null

已尝试设置windowsVerbatimArguments为true、注释node-pg-migrate内所有代码、添加文件路径到$PATH变量,但问题依旧,请问原因是什么?


问题原因与解决方法

核心原因

  1. Windows文件扩展名识别问题:自定义的node-pg-migrate文件没有.js扩展名,Windows系统无法识别这是可执行的Node.js脚本,spawn无法正确解析并打开文件。
  2. Shebang行语法错误:自定义文件的Shebang行#!usr/bin/env node缺少根路径斜杠,正确写法应为#!/usr/bin/env node——该问题在类Unix系统影响更大,但Windows下也需保证语法规范。
  3. Spawn调用逻辑错误:Windows下直接spawn脚本文件时,必须明确指定用Node.js程序来执行它,而非直接调用脚本路径。

解决步骤

步骤1:给自定义脚本添加扩展名

将node-pg-migrate重命名为node-pg-migrate.js,让Windows系统识别这是Node.js脚本文件。

步骤2:修正Shebang行(可选但规范)

修改node-pg-migrate.js的第一行为:

#!/usr/bin/env node

步骤3:调整Spawn调用逻辑

在migrate.js中,将spawn的执行主体改为node,把脚本路径作为第一个参数传入:

const child = spawn(
    'node', // 明确使用Node.js执行脚本
    [path.resolve(migrationsDir, 'node-pg-migrate.js'), ...spawnArgs], // 脚本路径作为第一个参数,后续跟上原参数
    { env: { ...process.env }, windowsVerbatimArguments: false }
);

步骤4:验证路径正确性

可以在代码中增加日志,确认path.resolve(migrationsDir, 'node-pg-migrate.js')指向的路径确实存在对应的文件。

额外说明

Windows系统中,spawn直接调用无扩展名文件时,只会匹配系统注册的可执行文件扩展名(如.exe、.bat),.js文件需要通过node命令明确执行。修改后的调用方式可同时兼容Windows和类Unix系统。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 14:20:23