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

执行脚本时yarn命令报错,直接运行node脚本却正常求助

问题:yarn install触发husky初始化脚本时出现文件找不到错误

我写了一段自动初始化husky的Node脚本,在Windows环境直接运行node install.js完全正常,但把它加到yarn install的postinstall脚本里执行时,却报错找不到.husky/commit-msg文件。直接执行脚本没问题,只有通过yarn触发才会出错。

初始化脚本代码

const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');

const root = __dirname;

function createSpawn(command, next) {
    const child = spawn(command, {
        stdio: 'inherit',
        shell: true,
        cwd: root,
    });
    child.on('exit', function () {
        if (typeof next === 'function') {
            next();
        }
    });
}

function install() {
    fs.rmSync(path.resolve(root, '.husky'), {
        recursive: true,
        force: true,
    });
    createSpawn('npx husky install', () => {
        createSpawn('npx husky add .husky/pre-commit "npm run pre-commit"', () => {
            createSpawn('npx husky add .husky/commit-msg "npx --no -- commitlint --edit #EE#"', () => {
                const file = path.resolve(root, '.husky/commit-msg');
                let content = fs.readFileSync(file).toString();
                content = content.replace('#EE#', '"$1"');
                fs.writeFileSync(file, content);
            });
        });
    });
}

install();

报错信息

yarn install v1.22.19
[1/4] 🔍  Resolving packages...
success Already up-to-date.
$ node install.js

node:internal/fs/utils:344
throw err;
^

Error: ENOENT: no such file or directory, open '/Users/ao/Desktop/Yeastar/PPV3/ppfe/.husky/commit-msg'
    at Object.openSync (node:fs:585:3)
    at Object.readFileSync (node:fs:453:35)
    at /Users/ao/Desktop/Yeastar/PPV3/ppfe/install.js:32:34
    at ChildProcess.<anonymous> (/Users/ao/Desktop/Yeastar/PPV3/ppfe/install.js:17:13)
    at ChildProcess.emit (node:events:526:28)
    at Process.ChildProcess._handle.onexit (node:internal/child_process:291:12) {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: '/Users/ao/Desktop/Yeastar/PPV3/ppfe/.husky/commit-msg'
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

问题分析

  1. 子进程事件监听逻辑缺陷:createSpawn只监听exit事件,但该事件仅表示子进程退出,不代表命令执行成功。如果npx husky add在yarn环境下执行失败,子进程依然会触发exit,导致后续回调盲目执行,尝试读取不存在的文件。
  2. 环境上下文差异:直接执行脚本和通过yarn执行时,环境变量、shell解析逻辑不同,可能导致npx命令行为异常,比如yarn接管包管理逻辑后,husky add未正确生成文件。
  3. 引号解析问题:husky add命令中的嵌套引号在不同shell下可能解析错误,导致命令实际执行结果不符合预期。

解决方案

方案1:改进子进程执行校验逻辑

修改createSpawn函数,监听close事件并检查退出码,确保前一步命令执行成功后再执行后续回调:

function createSpawn(command, next) {
    const child = spawn(command, {
        stdio: 'inherit',
        shell: true,
        cwd: root,
    });
    child.on('close', (code) => {
        if (code === 0 && typeof next === 'function') {
            next();
        } else {
            console.error(`命令执行失败: ${command},退出码: ${code}`);
            process.exit(1);
        }
    });
    child.on('error', (err) => {
        console.error(`命令无法启动: ${command},错误: ${err.message}`);
        process.exit(1);
    });
}

方案2:替换npx为yarn dlx

在yarn环境下使用yarn dlx替代npx,避免包管理工具的兼容问题:

function install() {
    fs.rmSync(path.resolve(root, '.husky'), {
        recursive: true,
        force: true,
    });
    createSpawn('yarn dlx husky install', () => {
        createSpawn('yarn dlx husky add .husky/pre-commit "npm run pre-commit"', () => {
            createSpawn('yarn dlx husky add .husky/commit-msg "npx --no -- commitlint --edit #EE#"', () => {
                const file = path.resolve(root, '.husky/commit-msg');
                let content = fs.readFileSync(file).toString();
                content = content.replace('#EE#', '"$1"');
                fs.writeFileSync(file, content);
            });
        });
    });
}

方案3:手动生成commit-msg文件

跳过husky add创建commit-msg,直接手动生成文件,避免引号解析问题:

function install() {
    fs.rmSync(path.resolve(root, '.husky'), {
        recursive: true,
        force: true,
    });
    createSpawn('npx husky install', () => {
        createSpawn('npx husky add .husky/pre-commit "npm run pre-commit"', () => {
            const commitMsgPath = path.resolve(root, '.husky/commit-msg');
            fs.mkdirSync(path.dirname(commitMsgPath), { recursive: true });
            // 直接写入husky脚本内容
            fs.writeFileSync(commitMsgPath, '#!/usr/bin/env sh\n. "$(dirname -- "$0")/_/husky.sh"\n\nnpx --no -- commitlint --edit "$1"\n');
            // 非Windows环境添加执行权限
            if (process.platform !== 'win32') {
                fs.chmodSync(commitMsgPath, 0o755);
            }
        });
    });
}

方案4:修复目录权限(仅macOS/Linux)

如果是类Unix系统,确保项目目录有足够读写权限:

chmod -R 755 /Users/ao/Desktop/Yeastar/PPV3/ppfe

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 04:45:54