Ruby rbenv system wide install (support for multi-user usecase)

ruohanc · 2013年12月21日 · 最后由 ruohanc 回复于 2014年09月07日 · 5223 次阅读
本帖已被设为精华帖!

起因

@luikore 吕大神的帖子 [姨妈] 终于把 rvm 换成 rbenv 了, 讨论 rbenv 比之 rvm 不足的地方, 我列了这么四点

  • rvm 傻瓜的帮你处理一些库依赖 (特别是在 osx 下系统 readline 和 brew 安装的 GNU readline 傻傻分不清楚的时候)
  • rvm 良好的处理了多用户服务器环境下的管理
  • 它官方有提供 offline 安装的方法, 对我来说很重要, 我有很多机器都不能上外网(生产环境安全要求严格).
  • 有一个 binary 功能, 可以让我自己打包一个适应本地环境的 ruby, 避免在每个服务器上编译(未验证)

今天来尝试用 rbenv 解决上述问题

整理下需求:

  1. 目标环境: 是 linux 下的 production 运行环境, 满足多用户共同使用的需求
  2. 库依赖: 只专注于解决第一个问题, 跨平台的库依赖问题不予解决(比如不同系统使用不同的包管理,不同的包名等问题)
  3. 离线安装: 能够完全只依赖有限的网络条件 offline 安装 (基本解决)
  4. 多用户支持: 使用 linux 组权限解决 rbenv 的 none root 用户使用问题(比如安装新 ruby, 切换默认 ruby, 全局性的安装&删除 gem)

最后的结果

多用户支持

通过 linux 的组权限解决, 不完美, 有点小问题.

问题在 umask 的设置上, 系统默认是 umask 022 即组权限默认抹去 写权限. 在类似的场景下可能会出现 permission deny: 用户 A 在 gem 的默认位置上安装了 gem A, 但是用户 B 想把它删掉

解决这个问题的根本办法是请在 production 环境里面使用 bundle install --deployment 谢谢!

离线安装支持

这部分没有写在脚本里, 按照两步走:

  1. 离线安装 rbenv 和 ruby-install: 简单, 打个 tar 包就好了
  2. 离线安装 ruby: 简单, 建立一个 $RBENV_PREFIX/cache 文件夹, 然后把 ruby 源代码放进去就好了

参考资料: Package download caching

部署运行方式

linux 的安全性问题就不赘言了, 总之你需要用一个独立的帐号来运行你的 rails app, 那么你应该这么做

折腾个什么劲啊, 用 capistrano-rbenv 呗

安装脚本参考

GIST 在此

PREFIX="/usr/local"
RBENV_PREFIX="$PREFIX/rbenv"
BIN_PATH="$PREFIX/bin"
RBENV_GROUP="rbenv"

umask 002

## Install rbenv, ruby-build and rbenv-gem-rehash
git clone git://github.com/sstephenson/rbenv.git $RBENV_PREFIX

mkdir $RBENV_PREFIX/plugins
git clone git://github.com/sstephenson/ruby-build.git $RBENV_PREFIX/plugins/ruby-build
git clone git://github.com/sstephenson/rbenv-gem-rehash.git $RBENV_PREFIX/plugins/rbenv-gem-rehash

## add rbenv script to PATH
ln -s $RBENV_PREFIX/bin/rbenv $BIN_PATH/rbenv

## Add rbenv to the System wide profile:
## @note profiles only will be sourced in `login shell`,
##       see the difference here(Chinese): https://gist.github.com/yegle/1564928
cat <<EOF > /etc/profile.d/rbenv.sh
# rbenv setup
export RBENV_ROOT=${RBENV_PREFIX}
eval "\$(rbenv init -)"
EOF

chmod +x /etc/profile.d/rbenv.sh
source /etc/profile.d/rbenv.sh

## set rbenv group property
groupadd $RBENV_GROUP
chown -R :rbenv $RBENV_PREFIX
find $RBENV_PREFIX -type d -exec chmod g+Xs {} \;

## Install Ruby
#rbenv install 1.9.3-p484
#rbenv install 2.0.0-p353
#rbenv global 2.0.0-p353

## Rehash:
#rbenv rehash

2013-12-28 Update: chef 线上部署参考方案

经过线上验证,rbenv + ruby 完全可以通过 tar 包的方式快速部署到每一个服务器上(每个环境打一次包,用上面提供的脚本就行),我这里有一个 chef 的配置给大家参考:

共收到 22 条回复

多行 echo redirect 用 heredoc 更简单哦

<<EOF > /etc/profile.d/rbenv.sh
  # rbenv setup
  export RBENV_ROOT=${RBENV_PREFIX}
  eval "\$(rbenv init -)"
EOF

rbenv 应该尽量安装到用户下。

#2楼 @alvin2ye 这是给 SA 部署方式的讨论啦, 你单机开发么千万别搞这么麻烦.

@ruohanc 可以加上

$ RUBY_CONFIGURE_OPTS="--with-readline-dir=`brew --prefix readline`"
rbenv install 2.0.0-p195

这样在pry或irb里才可以输入非ASCII字符

#5楼 @zealinux 嗯..解决方案总是有的, 但是找到这个解决方案的过程并不愉悦. 我的意思是如果你用 rvm, 完全不用受这个罪..

#1楼 @luikore 被你忽悠了,还以为真可以像你这样写,像下面这样才行噻

cat <<EOF > /etc/profile.d/rbenv.sh
# rbenv setup
export RBENV_ROOT=${RBENV_PREFIX}
eval "\$(rbenv init -)"
EOF

我正在做部署测试,回头再报告下结果。

#7楼 @ruohanc 哦, 原来只有 zsh 才能这么写...

#7楼 @ruohanc mark一下 @luikore 的失误

#9楼 @fsword #10楼 @luikore

走过,路过,不要错过。。。 😄

@huacnlee 新的部署方式!内网可以直接用我打好的包喔,gist 里面写的 IP 是内网可用的 IP 喔。

:bowtie:

标题容易让人误会,简单的说发布就可以了

#14楼 @iambowen 唔。。没发现误会的点呀~ 就是说一个系统级别的安装方式而已。

看到这个帖子,前段时间也研究了下, https://github.com/cao7113/rbenv-pluger

17楼 已删除
18楼 已删除
19楼 已删除

#7楼 @ruohanc 老大,你不能挖坑啊,

ruby-build 不是放到 plugins 就可以直接用吧,我在 14.04 下要安装的 ./install.sh,人家最开始的代码就挺好的啊:

# Install ruby-build:
pushd /tmp
  git clone git://github.com/sstephenson/ruby-build.git
  cd ruby-build
  ./install.sh
popd

另外 ## Install Ruby 之前要装依赖的:

apt-get install autoconf bison build-essential libssl-dev libyaml-dev libreadline6 libreadline6-dev zlib1g zlib1g-dev

你的 bash 里面没有 PATH 相关的内容,装完了不能用啊

Installed ruby-2.1.2 to /home/xxxxx/.rbenv/versions/2.1.2

还得加上:

echo 'export PATH="/home/xxxxx/.rbenv/versions/2.1.2/bin:$PATH"' >> /etc/profile.d/rbenv.sh

#20楼 @Peter rbenv init - 你运行下这个看看, 是包括了 PATH 的. 然后你的 PATH 是错的, 应该用 .rbenv/shims

装依赖跟你的系统相关, 我这里没有 cover ruby 的编译安装, 所以当然也没说

#20楼 @Peter btw...这个方法我已经线上稳定运行一年了.. 你先自己看看吧.

#21楼 @ruohanc 谢谢回复,我的确掉另一个坑里了,这个bash 要用 root 身份运行,我用的 sudo 提权,导致 source 这类命令不会被执行。

#22楼 @ruohanc 建议把:

ln -s $RBENV_PREFIX/bin/rbenv $BIN_PATH/rbenv
cat <<EOF > /etc/profile.d/rbenv.sh
# rbenv setup
export RBENV_ROOT=${RBENV_PREFIX}
eval "\$(rbenv init -)"
EOF

换成:

cat <<EOF > /etc/profile.d/rbenv.sh
# rbenv setup
export RBENV_ROOT=${RBENV_PREFIX}
export PATH=${RBENV_ROOT}/bin:${PATH}
eval "\$(rbenv init -)"
EOF

或者换成:

ln -s $RBENV_PREFIX/bin/rbenv $BIN_PATH/rbenv
cat <<EOF > /etc/profile.d/rbenv.sh
# rbenv setup
eval "\$(rbenv init -)"
EOF

如果你都 ln -s 了,那下面这句就没有任何意义了:

export RBENV_ROOT=${RBENV_PREFIX}

#24楼 @Peter 你可以试试看. 成功了告诉我, 反正写着也没事, 不纠结这个.

不过我怀疑不写会有问题, 比如你看这里 https://github.com/sstephenson/rbenv/blob/13a474c4e9c3305179b364723349fc49b3e935e3/libexec/rbenv#L39

if [ -z "${RBENV_ROOT}" ]; then
  RBENV_ROOT="${HOME}/.rbenv"
else
  RBENV_ROOT="${RBENV_ROOT%/}"
fi
export RBENV_ROOT
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册