package.json脚本及Node.js切换目录失效问题求助
你遇到的问题其实是脚本执行时的子进程隔离机制导致的,不管是shell命令还是Node.js进程,它们的目录变化都只局限在自己的进程里,没法影响父进程或者后续独立启动的子进程。我来逐个拆解你的尝试为什么失败,再给你可行的解决方案:
你的尝试为什么无效?
1. 直接在deploy脚本里写yarn build && cd ../../..
每个&&分隔的命令都是在独立的shell子进程中运行的。cd ../../..确实会切换那个临时子进程的目录,但这个子进程执行完就直接退出了,npm/yarn运行脚本的父进程工作目录完全没变化——就像你打开两个终端,在一个里cd目录,另一个终端的目录肯定不会变是一个道理。
2. 用Node.js的process.chdir或单独的Node脚本
process.chdir确实能改变当前Node进程的工作目录,但当这个Node进程运行结束后,后续的cf login是作为新的独立子进程启动的,它继承的是npm/yarn父进程的原始目录,而不是Node进程切换后的目录。所以终端里打印的目录是对的,但实际后续命令还是在原来的地方跑。
可行的解决方案
方案一:把需要在目标目录执行的命令放在同一个shell上下文里
让cd和后续命令共享同一个子进程,用括号包裹或者直接连写:
"deploy": "yarn build && (cd ../../.. && cf login)"
括号里的所有命令都会在cd切换后的目录下执行,因为它们属于同一个shell子进程,目录变化会持续到括号内的命令全部执行完毕。
方案二:写一个完整的shell脚本(推荐,更易维护)
把所有部署步骤放到单独的shell脚本里,比如创建deploy.sh:
#!/bin/bash # 先执行构建 yarn build # 切换到目标目录 cd ../../.. # 执行登录命令 cf login # 可以在这里添加其他需要在目标目录执行的命令
然后给脚本加执行权限:
chmod +x deploy.sh
最后修改package.json的脚本:
"deploy": "./deploy.sh"
这种方式所有步骤都在同一个shell进程里,目录切换自然会生效。
方案三:在Node脚本里直接执行后续命令
如果你想继续用Node.js处理,那得把cf login也放到Node进程里执行,而不是让Node进程结束后再单独跑。修改你的changedirectory.js:
const { execSync } = require('child_process'); try { // 切换目录 process.chdir('../../../'); console.log(`New directory: ${process.cwd()}`); // 在当前Node进程的上下文里执行cf login,继承已切换的目录 execSync('cf login', { stdio: 'inherit' }); // stdio: 'inherit'让命令输出直接显示在终端 } catch (err) { console.error(`操作失败: ${err.message}`); }
然后package.json脚本改成:
"deploy": "yarn build && node changedirectory.js"
这样后续命令会在Node已经切换后的目录下运行,因为execSync会复用当前Node进程的工作目录。
内容的提问来源于stack exchange,提问作者user3438917

