【问题标题】:Unable to install and run my own npm module in Linux无法在 Linux 中安装和运行我自己的 npm 模块
【发布时间】:2017-05-25 06:47:58
【问题描述】:

我创建了一个我打算发布的 npm 模块,但并非没有测试它首先可以工作。所以我安装了我正在使用的模块npm install -g .,它在我的 Windows 计算机上运行良好,但它不能在我的 Linux (Debian) 计算机上运行。相反,我收到以下错误:

15:52 $ transval
: No such file or directory

到目前为止,当我在我的 Windows 计算机上比较生成的 cmd 和 bash 文件时,我发现的唯一一件事是(当与“gulp”进行比较时)cmd 文件在 bash 文件的结构中是相同的不是。设置 basedir 的第二行不同。这是我的模块的已发布 bash 文件的完整输出:

#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

case `uname` in
    *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac

if [ -x "$basedir/node" ]; then
  "$basedir/node"  "$basedir/node_modules/transval/bin/transval.bin.js" "$@"
  ret=$?
else 
  node  "$basedir/node_modules/transval/bin/transval.bin.js" "$@"
  ret=$?
fi
exit $ret

但是,如果我将前两行与任何其他文件进行比较,就会有显着差异!这是任何其他模块的前两行,例如 gulp:

#!/bin/sh
basedir=`dirname "$0"`

所有其他 bash 文件都获得该目录名。如果我将我的 bash 文件更改为那个 basedir,它会突然起作用。快把我逼疯了!

编辑: 这两个文件是在我运行命令npm install -g .(从而全局安装我的包以进行测试)或发布时(即npm publish)创建的,所以我不会自己生成这些文件。 em>

我的 package.json 有一个 bin 条目,它指向一个如下所示的文件:

#!/usr/bin/env node

var app = require('../bundle.js');
app.init(process.argv);

有人知道为什么它可以在 Windows 上运行而不是在 Linux 上运行吗?

【问题讨论】:

  • echo/sed 序列将反斜杠更改为正斜杠。两者在我的 cygwin 系统上都是一样的。你是如何生成 bash 文件的? --- 另外,我看到您有一个解决方法(手动更改生成的 bash 脚本)。您的问题是如何避免每次更新模块时都必须进行手动更改?
  • 另请参阅this question and its answers,了解更稳健地获取$basedir 的方法。
  • 尝试使用${0%/*}。我一直在 Mac、Linux 和 Windows(cygwin 和 mingw)的所有脚本中使用它。像魅力一样工作。
  • 我已经稍微澄清了我的问题。当我通过npm install -g . 安装模块时会生成 cmd 和 bash 文件,所以我不知道它们是如何生成的,因此我不能只更改 basedir,因为它不适用于下载我的模块的其他人。
  • @cxw: bash 是版本:4.3.46(1)-release,sed 是版本 4.2.2 和 sh 不接受sh --version :)

标签: node.js linux bash npm


【解决方案1】:

编辑 根据the OP's answer 中的附加信息,这确实是一个行尾问题。这个问题实际上与$()`` 无关。

在 Windows 上生成时,行以回车和换行结束,\r\n。但是,在 Debian 上运行生成的脚本时,只有\n 被视为行尾。因此,对basedir 的分配实际上是:

basedir=$(dirname "...")$'\r'
                      # ^^^^^ Carriage return!  Oops!

我认为这就是为什么错误消息是':没有这样的文件或目录':在:之前,$basedir的内容实际上被打印出来了,以\r结尾。 \r 将光标移回行首,然后以: 开头的其余错误消息覆盖了路径。 (不过,这是一个猜测——我无法在我的系统上重现确切的错误消息。)

一种解决方法是在basedir 赋值之后放置一个 #(空格哈希):

basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") #
                                         # add these ^^

这样\r 将成为评论的一部分,而不是basedir 的一部分。


注意:有关获取$basedir 的其他方式,请参阅this question and its answers


每次聊天,OP 明天将为这两个选项添加 $basedir 值。

作为参考,这是我们目前所处的位置:

  • 每个this answernpm 会根据package.json 中的bin 条目生成包装脚本。
  • npm 使用 cmd-shim 模块制作脚本。
  • cmd-shim 已更新为 2013/10/28 以使用 dirname ... echo ... sed 序列,以便它可以在 msysgit 上运行。
  • gulp 和其他使用 dirname "$0" 的脚本可能是在更新之前使用 cmd-shim 生成的。
  • OP 的 Debian /bin/shapparently dash(当前为 0.5.7-4 in debian stable)。
    • 对于 OP,在 Debian 上,bash 是版本:4.3.46(1)-release,sed 是版本 4.2.2
    • 我在 Cygwin dash 0.5.8-3 上尝试了两种 basedir 类型,它们都有效。

在 Ubuntu 上,OP 有一个不同的问题:/usr/bin/env: 'node\r': No such file or directory。对我来说,这似乎是一个行尾问题,可能与 Debian 问题不同。

【讨论】:

    【解决方案2】:

    好的,找到问题了。从 Windows 发布似乎存在问题。 一旦我从 Linux 发布(在本例中为 Ubuntu),我就可以在 Linux 和 Windows 计算机上安装它。 我不确定这是什么原因,可能是一些 npm 错误或打瞌睡换行问题,但现在它正在工作:)

    我之前确实尝试过从 Linux 发布,但失败了,但是使用旧版本的 Node (4.something) 并且不起作用,但现在我已经升级到最新版本并且它运行良好,所以可能与它有关。

    编辑: 我现在可以验证在运行节点 6.2.2 的 Debian 机器上发布会创建一个无法使用的发布版本,而在运行节点 7.4.0 的 Ubuntu 机器上发布可以正常工作,并且可以在任何地方安装和运行。两台机器都在运行 npm 版本 4.0.5。

    【讨论】:

    • 你愿意帮我做一个测试,以便我提交一份完整的错误报告吗?这样以后就没有其他人会遇到这个问题,并且您将能够从任何平台生成。如果您愿意,请:(1) 在 Windows 上生成脚本; (2) 在 Windows 的记事本中打开 bash 脚本; (3)basedir= 行的末尾,添加一个空格和一个哈希(...)") #); (4) 在 Debian 上尝试修改后的脚本。这应该可行——请参阅我更新的答案以获取解释。请让我知道你是否会尝试它,如果是,它是如何工作的。谢谢!
    • 我会在星期一尝试,然后将结果回复给您:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-21
    • 2014-11-19
    • 1970-01-01
    • 2016-02-22
    • 2019-11-10
    • 2015-11-15
    • 1970-01-01
    相关资源
    最近更新 更多