运行节点 bin 脚本时确定命令行工作目录

Posted

技术标签:

【中文标题】运行节点 bin 脚本时确定命令行工作目录【英文标题】:Determine command line working directory when running node bin script 【发布时间】:2012-08-27 15:17:21 【问题描述】:

我正在创建一个节点命令行界面。全局安装,使用bin文件执行。

我计划在我正在处理的文件的根目录中打开一个命令窗口,然后只运行命令但是我无法确定当前的工作目录,因为process.cwd() 正在返回节点的目录包裹。我最初假设,由于代码是使用批处理文件作为包装器执行的(这就是 bin 文件在开始时没有节点的情况下执行的方式),所以这是不可能的,但 coffee-script 设法做到了。看了下coffee-script源码,没看懂(经验不够)。

要自己测试它,请使用此 package.json 文件创建一个包:


  "name": "test-package",
  "version": "1.0.0",
  "bin": 
    "test-package":  "./bin/test-package"
  ,
  "main": "/lib/test"

bin 中的这个测试包文件:

#!/usr/bin/env node

var path = require('path');
var fs   = require('fs');
var lib  = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');

require(lib + '/test');

任何人都可以对此有所了解。

然后尝试获取 lib/test 中的命令行目录。

【问题讨论】:

【参考方案1】: process.cwd() 返回执行命令的目录(不是节点包的目录),如果它没有被应用程序内部的 'process.chdir' 更改。 __filename 返回文件所在文件的绝对路径。 __dirname 返回__filename 目录的绝对路径。

如果您需要从模块目录加载文件,则需要使用相对路径。

require('../lib/test');

而不是

var lib  = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');

require(lib + '/test');

它总是相对于它调用的文件,不依赖于当前的工作目录。

【讨论】:

process.chdir()之后,有没有办法拿到原版? @reergymerej 您可能希望在执行 chdir() 之前先存储 cwd(例如,var originalCwd = process.cwd(); 然后执行您的 process.chdir(),然后您可以返回原始数据)。 ../lib/test 便携吗? 没有。它不是一个可移植的解决方案,因为 Windows 使用反斜杠。因此,如果您尝试在 Windows 中运行它,它将无法正常工作。 其实对于 NodeJS 这都是一样的。即使在 Windows 上,您也可以方便地以 Unix 方式要求相对路径。所以../lib/test 是可移植的,而Windows 对应的..\lib\test 不是...【参考方案2】:

或者,如果您只想获取当前 NodeJS 脚本的当前目录,您可以尝试类似这样的简单操作。请注意,这在 Node CLI 本身中不起作用:

var fs = require('fs'),
    path = require('path');

var dirString = path.dirname(fs.realpathSync(__filename));

// output example: "/Users/jb/workspace/abtest"
console.log('directory to start walking...', dirString);

【讨论】:

【参考方案3】:

当前工作目录

要获取当前工作目录,可以使用:

process.cwd()

但是,请注意,某些脚本,尤其是 gulp,会将当前工作目录更改为 process.chdir()

节点模块路径

您可以通过以下方式获取当前模块的路径:

__filename __dirname

原始目录(启动命令的位置)

如果您从命令行运行脚本,并且想要运行脚本的原始目录,无论脚本当前在哪个目录中运行,您都可以使用:

process.env.INIT_CWD

使用 NPM 脚本时的原始目录

有时需要在当前目录而不是项目的根目录中运行 NPM 脚本。

此变量在 npm 包脚本中可用:

$INIT_CWD.

您必须运行最新版本的 NPM。如果此变量不可用,请确保 NPM 是最新的。

这将允许您访问 package.json 中的当前路径,例如:

scripts: 
  "customScript": "gulp customScript --path $INIT_CWD"

【讨论】:

process.env.INIT_CWD 返回package.json的目录 注意,$INIT_CWD 仅适用于 Linux。对于 Windows,您必须使用 %INIT_CWD%。我认为这个问题可以通过使用 npmjs.com/package/cross-env 来解决,但我自己没有尝试过【参考方案4】:

path.resolve('.') 也是一个可靠且干净的选项,因为我们几乎总是require('path')。它将为您提供调用它的目录的绝对路径。

【讨论】:

【参考方案5】:

这对我有用:

console.log(process.mainModule.filename);

【讨论】:

以上是关于运行节点 bin 脚本时确定命令行工作目录的主要内容,如果未能解决你的问题,请参考以下文章

从命令行运行但不能通过 cron 运行时脚本运行良好

当它从命令行 bash 工作时,无法从 crontab 运行 bash 脚本

ETCD:单机单节点

终端打印

Shell脚本判断文件是不是存在

无法在 Beowulf 集群上正确运行个人作业。示例作业工作正常