使用 .bash_profile 和“postinstall"避免 NPM 全局安装脚本 [英] Avoiding NPM global install using .bash_profile and "postinstall" script

查看:19
本文介绍了使用 .bash_profile 和“postinstall"避免 NPM 全局安装脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

无论好坏,NPM 的理念是在 ./node_modules 中为项目本地安装所有必要的依赖项,并让 package.json 反映所有必要的依赖项.

NPM philosophy, for better or worse, is to have all necessary dependencies for a project to be locally installed, in ./node_modules, and for package.json to reflect all necessary deps.

我有一个库,它通常会从全局安装和本地安装中受益,类似于 Gulp、Mocha 等.

I have a library, that would typically benefit from both global installation and local installation, similar to Gulp, Mocha, etc.

上述最隐蔽的问题之一是全局版本和本地版本可能不同,从而导致给定项目的兼容性问题.

One of the most insiduous problems with the above, is that the global and local versions might differ, causing compatibility issues for a given project.

我想到我们可以通过在 .bash_profile 中创建一个别名来避免这个问题,如下所示:

It occurred to me that we could avoid this problem, by creating an alias in .bash_profile, something like this:

# bash psuedocode 
* alias gulp='using current working directory, find the locally installed gulp and run that'

我的库不是 Gulp,但你明白了.我知道很多开发人员不喜欢第三方写入他们的 bash_profiles 的想法,但我认为这有点保留,考虑到做这样的事情有零外部影响 (TMK).

My library is not Gulp, but you get the idea. I know a lot of devs don't like the idea of 3rd parties writing to their bash_profiles, but I think that is a bit anal-retentive, considering doing something like this has zero outside effects (TMK).

所以我有三个问题:

(1) 这是个好主意吗?

(1) Is this a good idea?

(2) 有没有类似的项目以及如何做?

(2) Are there any projects that do something similar and how?

(3) 我不擅长 bash 脚本,你如何编写 bash 脚本如果您是开发人员,则可以递归查找 node_modules/.bin/gulp从项目中的目录运行 gulp 命令但不在根目录中?

(3) I an not great with bash scripting, how do you write a bash script that can recursively look for node_modules/.bin/gulp if you the dev runs the gulp command from a directory that is within the project but not in the root?

我的想法是作为一个安装后脚本来

My thinking was that as a postinstall script to

npm install --save-dev gulp

我们会运行一个脚本

  1. 将以上行*添加到 .bash_profile
  2. 在该行中,我们将指向存储在/Users/you/.gulp 下的脚本,该脚本将负责定位本地安装的 gulp.

这样我们就无需全局安装模块,因为它们仅用于命令行方便,并缓解了不同软件包版本的问题.

This way we save the need for global installations of modules, when they are only used for command line convenience, as well as alleviating the problem of differing package versions.

推荐答案

我会一一解决你的3个问题:

I'll go through your 3 questions one by one:

(1) 这是个好主意吗?

(1) Is this a good idea?

不.自动更改用户的私人文件绝不是一个好主意,如果你这样做,我发现有几件事可能会出现严重错误 - 纯粹是用户的烦恼不得不清理你的程序,破坏用户的系统配置,严重的安全问题.

No. Changing user's private files automatically is never a good idea and I see several things that can go horribly wrong if you do that - from a pure annoyance of users having to clean after your programs, to breaking user's system config, to serious security problems.

(2) 有没有类似的项目以及如何做?

(2) Are there any projects that do something similar and how?

我希望不会.我永远不会运行任何与我的 .bash_profile 混淆的程序——即使我没有它.我有 .profile.bashrc.这对您来说是另一个问题-您确定您甚至知道要编辑什么吗?如果我使用我有时使用的 dashzsh 或其他一些 shell 怎么办?

I hope not. I would never run any program that messes with my .bash_profile - even though I don't have it. I have .profile and .bashrc. And that's another problem for you - are you sure you even know what to edit? What if I use dash which I use sometimes, or zsh or some other shell?

(3) 我不擅长 bash 脚本,如果开发人员从项目中的目录运行 gulp 命令但不是在根?

(3) I an not great with bash scripting, how do you write a bash script that can recursively look for node_modules/.bin/gulp if you the dev runs the gulp command from a directory that is within the project but not in the root?

如果您不擅长 bash 脚本,那么您的绝对不应该自动编辑用户的私人文件.

If you are not great with bash scripting then your definitely should not edit user's private files automatically.

可以做的是在一个单独的文件中提供某个别名或 bash 函数为了用户的方便,并解释用户如何在他们的 .bashrc 如果他们愿意.

What you can do is to provide a certain alias or bash function in a separate file for user's convenience and explain how users can source your file inside of their .bashrc if they want to.

但永远不要替他们做决定.如果出现任何问题,这甚至会对您产生法律后果.

But never make that decision for them. If anything goes wrong this can even have legal consequences for you.

回答您在评论中发布的问题,我将添加几句话来说明函数在 Bash 中的工作原理.

Answering your questions posted in the comments, I'll add few words on how functions work in Bash.

我在 GitHub 上的脚本集合中,我几乎没有关于 如何安装它们如何使用它们.他们的源代码可在这里获得.

In my collection of script on GitHub I have few functions with instructions on how to install them and how to use them. Their source code is available here.

该集合中的一个示例函数是 ok - 这是它的源代码:

An example function in that collection is ok - this is its source code:

ok() {
  # prints OK or ERROR and exit status of previous command
  s=$?
  if [[ $s = 0 ]]; then
    echo OK
  else
    echo ERROR: $s
  fi
}

您可以从以下网址下载它(以及一些其他相关功能):

You can download it (with some other related functions) from:

如果你把它保存为 ~/ok-functions 那么你可以运行:

If you save it as ~/ok-functions then you can either run:

source ~/ok-functions

让它们在该会话中可用,或者您可以将该行放入 .profile.bashrc 以在每次登录后使其可用.您可以像使用普通命令或程序一样使用它:

to have them available in that session, or you can put that line in .profile or .bashrc to have it available after every login. You can use it as if it was a normal command or program like this:

ls /bin; ok
ls /binn; ok

防止全局安装的工作示例

我编写了一个 Bash 函数来执行您正在尝试执行的操作 - 它停止某个模块的全局安装 - 在此示例中称为 modname.将其保存到某个文件 - 例如到 ~/no-global-restricted-module - 当然您可以更改 n 中的 restricted-module 名称和 n 中的警告消息代码>w 以满足您的需求:

Working example of preventing global install

I wrote a Bash function that does what you are trying to do - it stops global installation of a certain module - called modname in this example. Save it to some file - e.g. to ~/no-global-restricted-module - of course you can change the restricted-module name in n and the warning message in w to suit your needs:

npm() {
  n=restricted-module
  w="Please don't install $n globally - see: http://example.com/"
  i=0
  g=0
  m=0
  for a in "$@"; do
    case $a in
      i|install)
        i=1;;
      -g|--global)
        g=1;;
      $n)
        m=1;;
    esac
  done
  if (( $i == 1 && $g == 1 && $m == 1 )); then
    echo $w >&2
    return 1
  else
    `which npm` "$@"
  fi
}

然后将此行添加到您的 ~/.profile~/.bashrc:

And then add this line to your ~/.profile or ~/.bashrc:

source ~/no-global-restricted-module

现在,当您再次登录或打开新的终端窗口时,您可以尝试在命令行中运行:

Now when you log in again, or when you open a new terminal window, you can try running this in your command line:

npm install --global restricted-module

您应该会看到一条警告,并且不会开始安装.如果您输入其他模块名称或省略 --global 开关,则安装应照常进行.这也适用于 i 而不是 install-g 而不是 --global 的快捷方式.

You should see a warning and no installation will be started. If you enter some other module name or you omit the --global switch then the installation should proceed as usual. This also works with the shortcuts of i instead of install and -g instead of --global.

这几乎就是你想要做的.您可以在文档中包含该函数以及如何使用它的说明.我特此根据 MIT 许可条款发布它,以便您可以自由使用它.我在 GitHub 上发布了它,其中包含更多配置选项和有关如何使用它的信息,请参阅:

This is pretty much what you are trying to do. You can include that function in your documentation with instructions on how to use it. I am hereby releasing it under the terms of the MIT license so you can use it freely. I published it on GitHub with some more options for configuration and information on how to use it, see:

另请参阅 此答案在终端播放各种声音的例子中更好地解释了编写、安装和使用 Bash 函数.

See also this answer for a much better explanation of writing, installing and using Bash functions on the example of playing various sounds in the terminal.

这篇关于使用 .bash_profile 和“postinstall"避免 NPM 全局安装脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆