ローファイ日記

出てくるコード片、ぼくが書いたものは断りがない場合 MIT License としています http://udzura.mit-license.org/

rbenv環境で「今使われている本物の」rubyバイナリを当てる

小ネタです。

rbenv環境で使う ruby コマンドは、実はラップしたシェルスクリプトであることは知られています。では、最終的に呼び出される本物のRubyはどこに埋まっているのか?

[追記] rbenv which

下の記事を書いたら教えてもらいました。一般的にはこのサブコマンドを使うと思います。

$ rbenv which ruby
/home/vagrant/.rbenv/versions/2.6.4/bin/ruby

Linux の場合

上記方法の他に、ラッパーシェルスクリプトが最終的に本物の ruby に execve することを利用すれば、最後に呼ばれる execve の引数が本物です。

$ strace -e execve -- ruby -v
execve("/home/vagrant/.rbenv/shims/ruby", ["ruby", "-v"], 0x7ffd702592a0 /* 23 vars */) = 0                                                              
execve("/home/vagrant/bin/bash", ["bash", "/home/vagrant/.rbenv/shims/ruby", "-v"], 0x7ffe3cc878d0 /* 23 vars */) = -1 ENOENT (No such file or directory)
execve("/home/vagrant/.rbenv/shims/bash", ["bash", "/home/vagrant/.rbenv/shims/ruby", "-v"], 0x7ffe3cc878d0 /* 23 vars */) = -1 ENOENT (No such file or d

...
execve("/home/vagrant/.rbenv/versions/2.6.4/bin/ruby", ["ruby", "-v"], 0x5629ff3d32a0 /* 27 vars */) = 0                                                
ruby 2.6.4p104 (2019-08-28 revision 67798) [x86_64-linux]
+++ exited with 0 +++

ということでこの環境では /home/vagrant/.rbenv/versions/2.6.4/bin/ruby でした。このやり方は、各種 *env でも使えるかと思います。

$ file `which ruby`
/home/vagrant/.rbenv/shims/ruby: Bourne-Again shell script, ASCII text executable
$ file /home/vagrant/.rbenv/versions/2.6.4/bin/ruby
/home/vagrant/.rbenv/versions/2.6.4/bin/ruby: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=c77720ccb985668bdb2377e7168f92f9bdfc7ba3, with debug_info, not stripped

通常 rbenv which でいいと思いますが、 strace にはこういう使い方もあるよ、という例として。。

Mac の場合

dtruss という同等のツールが入っている、ので、できるんだと思うけど、最近のMacではデフォルトで利用に制約があり、めちゃくちゃ面倒な手順を踏まないとその制約を解除できない。

というオチ。

参考。

stackoverflow.com