Create a Debian package from a Ruby gem - ruby

I'm attempting to create a Debian package for a simple utility I wrote with fpm and bundler but am having difficulties. Here's how I generate my .deb (I assume you've checked out sns and are in it's root):
$ bundle install
$ rake install
$ fpm -s gem -t deb --prefix /var/lib/gems/1.8/ pkg/sns-0.1.1.gem
Successfully installed sns-0.1.1
1 gem installed
md5sum: : No such file or directory
Created /home/blt/projects/com/carepilot/sns/rubygem-sns_0.1.1_all.deb
$ dpkg-deb -c rubygem-sns_0.1.1_all.deb | grep sns_hosts
-rwxr-xr-x root/root 762 2011-08-18 22:28 ./var/lib/gems/1.8/gems/sns-0.1.1/bin/sns_hosts
-rwxr-xr-x root/root 398 2011-08-18 22:28 ./var/lib/gems/1.8/bin/sns_hosts
Which is how it should be. Unfortunately
$ cat /var/lib/gems/1.8/bin/sns_hosts
#!/home/blt/.rbenv/versions/1.9.2-p290/bin/ruby
#
# This file was generated by RubyGems.
#
# The application 'sns' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'rubygems'
version = ">= 0"
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
version = $1
ARGV.shift
end
gem 'sns', version
load Gem.bin_path('sns', 'sns_hosts', version)
The gem creates a shunt which incorrectly sets the ruby interpreter to that of my development environment; rather a problem when pushing to other computers. How might I influence the interpreter which is set in the shunt script?

gem install has -E parameter to rewrite the shebang line to use /usr/bin/env. So you need to edit fpm to do this while packaging the gem. /usr/lib/ruby/gems/1.8/gems/fpm-0.3.7/lib/fpm/source/gem.rb line 120 has the parameters, you can try to add it there.

Related

How to use Ruby CGI scripts on Uberspace

I want to use Ruby CGI scripts on an Uberspace 7, but ran into several issues with permissions and security settings, in particular when using gems. How do I install CGI scripts with custom gems?
First, note that Uberspace 7 runs on SELinux. This means that CGI script files in ~/html/ not only have to be executable but also need the correct SELinux context. In this case, the type must be httpd_sys_content_t.
You can view the SELinux context with ls -lZ:
$ ls -Z file1
-rw-rw-r-- user1 group1 unconfined_u:object_r:user_home_t:s0 file1
If some files have the wrong context, the context can be restored with the restorecon command, e.g. restorecon -R ~/html/.
The user installation directory for Ruby gems is ~/.gem/. On Uberspace, gem install installs into that directory by default:
$ cat /etc/gemrc
gem: --no-document --user-install
As the home directory cannot be accessed by the apache process, gems installed there cannot be executed from CGI scripts. You can install gems in /var/www/virtual/$USER/gem instead, create the directory with
$ mkdir /var/www/virtual/$USER/gem
You cannot use the --install-dir parameter for gem install directly as this conflicts with the default parameters mentioned above:
$ gem install mygem --install-dir /var/www/virtual/$USER/gem
ERROR: Use --install-dir or --user-install but not both
Instead, create ~/.gemrc with the following content to override the default parameters (replace <USERNAME> with your actual user name):
gem: --install-dir /var/www/virtual/<USERNAME>/gem
Now the installation of gems should work:
$ gem install mygem
To use the gems in CGI scripts, set the Gem.paths variable before requiring gems:
#!/usr/bin/ruby
Gem.paths = { 'GEM_PATH' => '/var/www/virtual/<USERNAME>/gem' }
require 'mygem'
(... rest of the script)
This is needed as we cannot modify the environment variables (i.e. set GEM_PATH) for the apache process.

How to install gem via Makefile if it doesn't exist

I'm creating a Makefile for my project:
build:
sudo gem install sass
Any time I build it's asking me for my superuser password. If I remove sudo it will not install at all, but throw an error instead, as I don't have permissions to install a gem.
So I came up with an idea, that I want to check whether the gem already exists, and run installing command only when it doesn't.
So the question is how to perform this check inside Makefile.
From the command line you can see if a gem is installed with gem list <gemname>. This prints out a list of installed gems that match <gemname>:
$ gem list sass
*** LOCAL GEMS ***
sass (3.4.13, 3.4.1, 3.2.19)
sass-rails (5.0.1, 4.0.3)
The argument is actually a regex, so you can be more specific, checking e.g. only the Sass gem itself:
$ gem list \^sass\$
*** LOCAL GEMS ***
sass (3.4.13, 3.4.1, 3.2.19)
The -i flag to list makes it produce output more usable in scripts, printing true or false, and having a suitable exit status:
$ gem list \^sass\$ -i
true
$ echo $?
0
$ gem list \^notsass\$ -i
false
$ echo $?
1
You can combine this with Make’s conditionals, and the shell function (assuming GNU make) to check if a gem is installed from your makefile:
ifeq ($(shell gem list \^sass\$$ -i), false)
gem install sass
endif
(The extra $ is needed to prevent make trying to expand it as a variable.)
It's now traditional in the Ruby community to use Bundler to manage / install dependencies. This will install Gems without you having sudo privs, and also will keep different Ruby project's gems separate.
If you must install the gem raw, look into RVM or rbenv which both install Ruby and any future gems in your home directory. There' some logic you'd have to add to your Makefile to get it to use the new Ruby in your home folder (rbenv may make this easier than rvm, although Idon't know for sure)... but it's not hard.
One quick way to accomplish the task is writing an .rb script and execute it from a Makefile. The simplest script I came up with goes as follows:
#!/usr/bin/env ruby
if !Gem::Specification::find_all_by_name('sass').any?
exec("sudo gem install sass")
end
find_all_by_name is always returning an array and doesn't raise an error when it can't find anything (as find_by_name does).
Makefile:
default:
./install.rb
Make sure install.rb is executable:
chmod +x install.rb
Run it using make.

Ruber don't start

When I run ruber on console i got this information:
`require': cannot load such file -- korundum4 (LoadError)
I have installed korundum4 and any other ruby bindings. I use rvm.
I use: Kubuntu 12.04
On IRB is the same error, when I require "korundum4".
My $LOAD_PATH for system:
["/usr/local/lib/site_ruby/1.9.1", "/usr/local/lib/site_ruby/1.9.1/x86_64-linux", "/usr/local/lib/site_ruby", "/usr/lib/ruby/vendor_ruby/1.9.1", "/usr/lib/ruby/vendor_ruby/1.9.1/x86_64-linux", "/usr/lib/ruby/vendor_ruby", "/usr/lib/ruby/1.9.1", "/usr/lib/ruby/1.9.1/x86_64-linux"]
So as you see, Ruby loads gems that are installed inside RVM. If you want to run your app with system wide libraries you need to switch RVM to system Ruby using:
$ rvm use system
or read this https://rvm.io/integration/qtruby/ how to integrate QtRuby int RVM (I don't tested this).
I found better solution:
gem install qtbindings
Works with Qt4 and rvm.
My new great solution:
dependencies.sh
#!/bin/bash
if [[ $USER -eq 'root' ]]; then
exit 1
fi
sudo apt-get install libqt4-core libqt4-dev automoc ruby2.0-dev
wget http://rubyforge.org/frs/download.php/71843/qt4-qtruby-2.1.0.tar.gz
tar -xvzf qt4-qtruby-2.1.0.tar.gz
cd qt4-qtruby-2.1.0
rvm install 2.0.0
rvm use 2.0.0
rvm gemset gui
rvm use 2.0.0#gui
sed 's/Config::/RbConfig::/' cmake/modules/FindRuby.cmake > cmake/modules/FindRuby.cmake1
sed 's/ruby19/ruby19 ruby2 ruby20 ruby200 ruby2.0/' cmake/modules/FindRuby.cmake1 > cmake/modules/FindRuby.cmake2
mv cmake/modules/FindRuby.cmake2 cmake/modules/FindRuby.cmake
sed 's/Config::/RbConfig::/' cmake/modules/FindRUBY.cmake > cmake/modules/FindRUBY.cmake1
sed 's/ruby19/ruby19 ruby2 ruby20 ruby200 ruby2.0/' cmake/modules/FindRUBY.cmake1 > cmake/modules/FindRUBY.cmake2
mv cmake/modules/FindRUBY.cmake2 cmake/modules/FindRUBY.cmake
mkdir build
cd build
cmake ..
make
sudo make install
sudo ldconfig /usr/local/lib
sudo chown -R $USER:$USER $MY_RUBY_HOME
cd ../..
And after that you can do:
app.rb
require 'rubygems'
require 'eventmachine'
require 'Qt4'
app = Qt::Application.new(ARGV)
hello_button = Qt::PushButton.new("Hello EventMachine")
hello_button.resize(100,20)
hello_button.show
EventMachine.run do
EM.add_periodic_timer(0.01) do
app.process_events
end
end
Gemfile
source 'http://rubygems.org'
gem 'eventmachine'
This way you can use ruby 2.0.0 with smoke and Qt4.

Ruby cannot find required libraries even though gem is installed

I have spent literally days trying to install ruby 1.9.2 and get it working with gems :-/ I eventually gave up on my Mac OSX 10.6 machine and below is the current state on my Ubuntu machine. Any advice would be greatly appreciated!
# ruby test.rb
<internal:lib/rubygems/custom_require>:29:in `require': no such file to load -- mongo (LoadError)
from <internal:lib/rubygems/custom_require>:29:in `require'
from test.rb:1:in `<main>'
# cat test.rb
require 'mongo'
db = Mongo::Connection.new.db("mydb")
# gem which mongo
/usr/local/rvm/gems/ruby-1.9.2-p0/gems/mongo-1.1.2/lib/mongo.rb
# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=10.10
DISTRIB_CODENAME=maverick
DISTRIB_DESCRIPTION="Ubuntu 10.10"
According to this page: http://docs.rubygems.org/read/chapter/19
I symlinked which ruby I was using to match that which gem is using:
# which ruby
/usr/local/rvm/bin/ruby
# ls -l `which ruby`
lrwxrwxrwx 1 root root 44 2010-11-17 13:25 /usr/local/rvm/bin/ruby -> /usr/local/rvm/rubies/ruby-1.9.2-p0/bin/ruby
# gem env | grep 'RUBY EXECUTABLE'
- RUBY EXECUTABLE: /usr/local/rvm/rubies/ruby-1.9.2-p0/bin/ruby
# which gem
/usr/local/rvm/bin/gem
# gem -v
1.3.7
# ruby -v
ruby 1.9.2p0 (2010-08-18 revision 29036) [i686-linux]
Try putting the following line at the beginning
require "rubygems"
Why is "rvm" displaying in your /usr/local/rvm/ path? Did you do a system-wide install, as a system administrator using administering Ruby system wide for multiple users?
Did you add [[ -s '/usr/local/lib/rvm' ]] && source '/usr/local/lib/rvm' to your ~/.bashrc, ~/.bash_profile or ~/.profile (whichever you have configured)?
For normal, every day use, I recommend RVM's default setup:
RVM installation, RVM gems management.
Note to self: Buy stock in RVM. It's too cool.
Does it work under Ruby 1.8.7, which is pre-installed by default on OS X?
If so, one difference between 1.9.1 and 1.9.2 is that "." isn't part of $:'s path any more.
I recommend that you do rvm implode and delete the current setup. Then use the railsready script to setup RVM and Ruby properly for you on Ubuntu. It's important to understand that until you know what you are doing you should run the script as a user. Hope that helps.
On linux and OS X, I have always had to put require "rubygems" in the beginning. However it has always worked fine without this line on windows.

Build and run ruby without installing it to system directories

I've cloned the ruby 1.8.7 source tree. I can build ruby. But I can't figure out how to run it without installing it in system directories. How can I do it?
Background: I want to use "git bisect" to figure out which build of Ruby introduced a new behavior in my code. I need to build and run ruby against a test program, multiple times, but I don't want to clobber the ruby that the Debian package installed.
Here's what I get if I try to run the ruby I built from source:
$ ./ruby -e 'puts RUBY_VERSION'
ÀÇ ÀÇ : ÀÇ ÀÇ : cannot open shared object file: No such file or directory - ÀÇ ÀÇ (LoadError)
I've also tried installing it, but not to the system directories, and got a stack trace:
$ ./configure --prefix=/home/wayne/tmp/ruby/installed --exec-prefix=/home/wayne/tmp/ruby/installed
$ make
$ make install
$ /home/wayne/tmp/ruby/installed/bin/ruby -e 'puts RUBY_VERSION'
/home/wayne/tmp/ruby/installed/lib/ruby/1.8/openssl/ssl.rb:26: uninitialized constant OpenSSL::SSL::VERIFY_PEER (NameError)
from /home/wayne/tmp/ruby/installed/lib/ruby/1.8/openssl.rb:23:in `require'
from /home/wayne/tmp/ruby/installed/lib/ruby/1.8/openssl.rb:23
I've got the feeling that I'm close, but a miss is as good as a mile.
rvm is a great tool. and should be able to take care of the heavy lifting for switching between different ruby version (or even sets of gems).
Installation is very easy:
$ gem install rvm && rvm-install
$ echo "if [[ ! -z $HOME/.rvm ]] ; then source $HOME/.rvm ; fi" >> ~/.bash_profile
Then to install a specific version & patch level:
rvm install ruby-1.8.7-p160
Then to switch between versions:
$ rvm 1.8.7-p160
$ ruby -v
ruby 1.8.7 (2009-06-12 patchlevel 160) [i686-darwin10.0.0]
$ rvm 1.8.7-p174
ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin10.0.0]
When I need to do something like that, I use the chroot command. Create a temporary directory, install ruby into a sbin subdirectory, and chroot into the temp folder. Depending on what you are testing, you may also have to copy some system libraries into the temporary directory tree (before you chroot in).
It's probably easier to use rvm to test your app against different rubies.

Resources