RVM在SSH上无法工作

23

RVM在SSH上无法工作。

在命令行中:

leifg@host:~$ which ruby
/usr/local/rvm/rubies/ruby-1.9.2-p290/bin/ruby

通过SSH连接:

local:~$ ssh leifg@server 'which ruby'
/usr/bin/ruby

我正在使用 Ubuntu 11.04。

如何让 SSH 使用系统上与其相同的 Ruby?

我已经验证了一些先决条件:

  • Ruby 已经使用 apt-get install ruby 安装。这会有任何影响吗?
  • sshd_config 选项为 "PermitUserEnvironment yes",并已重新启动守护程序。

服务器上的 .bashrc 包含这些行,但当我删除它们时,看到的行为是相同的:

if [ -s "$HOME/.rvm/scripts/rvm" ] ; then
  . "$HOME/.rvm/scripts/rvm"
elif [ -s "/usr/local/rvm/scripts/rvm" ] ; then
  . "/usr/local/rvm/scripts/rvm"
fi

你说的“over ssh”是什么意思?是指通过ssh连接到同一系统吗? - fl00r
我想使用ssh user@host 'command'语法在另一个系统上执行Ruby,就像这两个代码片段中所解释的那样。在这种情况下,这是两台独立的机器。 - leifg
哇,那么你应该先在远程系统上安装rvm。 - fl00r
1
@Michael-kohl说,你的命令不会在shell中执行,但是@leifg如果你运行这个命令会发生什么?local:~$ ssh leifg@server 'source ~/.bashrc && which ruby' - Rakesh Sankar
尝试了几个技巧:ssh user@server 'source ~/.bashrc && which ruby',ssh user@server 'bash -c 'which ruby'',但都没有帮助。我不想将特定路径添加到/etc/environment中,因为这会覆盖所有用户的设置(我只想为特定用户设置)。有没有办法在ssh登录时执行rvm正在执行的任何操作? - leifg
10个回答

52
实际上,您的~/.bashrc将被执行。问题通常是添加了一个

标签,这会导致命令无法正确执行。
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*

在文件底部添加上述代码片段。然而,在Ubuntu系统上,默认的.bashrc文件在顶部包含以下内容。
# If not running interactively, don't do anything
[ -z "$PS1" ] && return

该调用会停止执行脚本的其余部分,因此不会设置正确的路径。所以你可以将rvm调用放在文件顶部,或者删除return调用。


这是正确的解决方案!复制上面的代码片段并在您的.bashrc顶部添加“rvm --default 1.9.2”,您就可以愉快地使用了。 - ayckoster
实际上,~/.bashrc 并不总是被执行。 - vikki
终于解决了。非常感谢。这真是太难找了。 - tulio84z
3
在Ubuntu上,这个方法解决了我的问题。值得注意的是,在我的情况下,“如果不是交互式运行,则不执行任何操作”的默认.bashrc代码略有不同:case $- in *i*) ;; *) return;; esac - skillet-thief
您可能需要确保上面的路径在您的计算机上是正确的。我的路径不同。我使用了这个搜索函数find / -type f -name "rvm"来查找我的RVM在其他地方,并成功地使用了这个命令[[ -s "/usr/local/rvm/scripts/rvm" ]] && source "/usr/local/rvm/scripts/rvm" # Load RVM into a shell session *as a function*。谢谢! - Alex Levine

19

ssh 的手册页面中得知:

如果指定了命令,则会在远程主机上执行它,而不是登录shell。

这意味着你的 .bashrc 文件不会被调用,所以 RVM 也不会被设置。

解决方案

最终以下代码解决了这个问题:

ssh <host> bash --login -c <command>

通过SSH以登录shell的形式启动bash,然后使用SSH的-c选项启动安装了RVM的Ruby。


1
换句话说,就是没有解决方案? - leifg
你尝试过在执行命令之前手动进行资源获取吗?或者手动设置适当的环境变量? - Michael Kohl
请提供需要翻译的英文内容,我会帮您快速准确地进行翻译。 - leifg
最后一个想法:ssh <host> bash --login -c <command>。通过SSH运行bash作为登录shell,然后通过-c选项运行您的Ruby脚本。 - Michael Kohl
@MichaelKohl,噢,对我没用,请问您能看一下我的问题吗?在这里 - gaussblurinc

16

实际上还有另一个更安全、更轻量级的选择。

在 /etc/(open)ssh 的 sshd_config 文件中添加 "PermitUserEnvironment yes"。

现在你可以在 /home/user/.ssh/environment 中指定用户环境。那么你要在那里放什么呢?

只需要像下面这样:

user# env | grep rvm > ~/.ssh/environment

这样就会产生以下结果:

user@app3:~$ cat ~/.ssh/environment 
rvm_bin_path=/usr/local/rvm/bin
GEM_HOME=/usr/local/rvm/gems/ree-1.8.7-2012.02
IRBRC=/usr/local/rvm/rubies/ree-1.8.7-2012.02/.irbrc
MY_RUBY_HOME=/usr/local/rvm/rubies/ree-1.8.7-2012.02
rvm_path=/usr/local/rvm
rvm_prefix=/usr/local
PATH=/usr/local/rvm/gems/ree-1.8.7-2012.02/bin:/usr/local/rvm/gems/ree-1.8.7-2012.02@global/bin:/usr/local/rvm/rubies/ree-1.8.7-2012.02/bin:/usr/local/rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
rvm_version=1.14.5 (stable)
GEM_PATH=/usr/local/rvm/gems/ree-1.8.7-2012.02:/usr/local/rvm/gems/ree-1.8.7-2012.02@global

注意:这也适用于用户安装 RVM(不仅适用于系统范围)。

现在你可以在 ssh 非交互式会话中使用 ruby 了:

ssh user@app3 'ruby --version'
ruby 1.8.7 (2012-02-08 MBARI 8/0x6770 on patchlevel 358) [x86_64-linux], MBARI 0x6770, Ruby Enterprise Edition 2012.02

完成!


我最喜欢这个,它看起来绝对最干净。它在我的机器上运行得非常好。谢谢!(哦,我正在使用带有VirtualMin的CentOS) - Joshua F. Rountree
我不喜欢这个使用精确的版本号,为什么不让rvm来处理呢? - Mark Murphy
@wojciechz 参考我的先前评论,我可以看到 Ruby 的路径可以更改为 "/usr/local/rvm/rubies/default",但是宝石的路径呢? - Mark Murphy
我相信有一个“默认”或通用的宝石路径,但是当您想要指定自己的自定义路径时,为什么要使用“默认”路径呢?例如,一个用户运行3个具有3个不同Ruby版本的应用程序? - wojciechz
1
我认为这应该是最好的答案 :) - Zoker

3
"rvm"存在两个调用错误:默认安装会删除文件/etc/profile.d/rvm.sh,并认为任何bash技巧现在都是全局可用的。- 这种假设是错误的。 /etc/profile.d/中的文件在登录时被“引用”,但可能不是从bash,甚至不是从shell。因此,它安装的cd钩子在运行这些文件的shell退出后不再存在。实际上,由于“rvm”安装此钩子的错误方式,在登录shell中运行裸露的bash时,它已经消失了!
我不知道“rvm”是否支持显式调用虚拟环境,而无需依赖于cd进入某个目录(这是我认为的第二个bug)。
有一个明智的解决方法:
使您的shell从例如~/.bashrc中引用/etc/profile.d/rvm.sh.bashrc在任何非登录bash中执行,并且通常会设置登录bash从那些登录shell文件中引用.bashrc,如~/.profile 对于您的ssh问题:适当的ssh shell不应该是登录shell吗?

2
我刚刚在 ~/.bashrc (针对git用户) 的顶部添加了这个字符串:
[[ -s "/usr/local/rvm/scripts/rvm" ]] && source "/usr/local/rvm/scripts/rvm"

1
  1. (如果使用Capistrano) 不要使用rvm1/capistrano3或rvm/capistrano; 不要设置:pty。

  2. 更改服务器上的运行用户的~/.rvmrc为此内容-请注意,它必须出现在自动退出交互式运行时的那一行之前:

# get rvm for non-interactive shells (eg capistrano) too
source /etc/profile.d/rvm.sh
export BASH_ENV=$HOME/.bashrc
export rvm_is_not_a_shell_function=0

# If not running interactively, don't do anything
[ -z "$PS1" ] && return 

1
我遇到了同样的问题。后来发现我不小心为多个用户安装了RVM。按照zoonmix的建议删除/usr/local/rvm目录并编辑~/.bashrc后,问题得以解决。

1
提到的解决方案肯定可以正常运行,但我的解决方案是运行
source /usr/local/rvm/environments/<ruby version>@<gemset version>

在远程SSH调用的开始处。例如:
ssh -l <remote username> <server ip> "source /usr/local/rvm/environments/<ruby version>@<gemset version> ; <rest of the remote script>"

0

请确保在服务器上执行了类似于 rvm --default 1.9.2 的操作,将 RVM 的 Ruby 设置为默认值。否则,它将始终使用默认的系统 Ruby。


0

Zoomix是最好的解决方案。但是当你在终端中使用"ruby rvm use system"或其他命令进行更改时,会出现错误: 警告!PATH没有正确设置,不在第一位...为了解决这个问题,在返回之前将代码片段放在.bashrc文件的顶部而不是在顶部(这里是Debian Jessie)。

case $- in
*i*) ;;
  *) 
  [[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*
  return;; esac

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接