How can I make a Ruby gem package copy files to ar

2019-02-18 12:39发布

问题:

Suppose you have a software package. You want to make it a gem, because gems are the de facto standard way to distribute anything in the Ruby world. Gems are great -- for libraries. But for real applications, the Rubygems system seems lacking. Only "recently" did they introduce a way to mark executables to be placed in somewhere in the system wide executable PATH. Unfortunately, Ruby gems still seems to be wanting in other aspects of software packaging, namely putting configuration files in places like /etc, or documentation under /usr/share/doc. Or is it? My question is:

Can I put instructions or code in a gemspec to have configuration installed into /etc, and documentation under some sensible, standardized place (like /usr/share/doc)? Or perhaps, as a workaround, can a post-install script be run to do these things?

For reference: the GemSpec specification.

Note that rubygems.org is down at the time of this writing. Here's the Google cache of that page: http://74.125.95.132/search?q=cache:JwJO6slR4BwJ:www.rubygems.org/read/chapter/20+http://www.rubygems.org/read/chapter/20%23page85&hl=en&ct=clnk&cd=1

If you examine the specification.rb file in the repo, and scroll down towards the end (search for ":section: Required gemspec attributes"), you can see what appear to be the currently supported attributes. I see nothing in there that looks like what I want.

回答1:

The short answer: no

The long answer: You should not want/need to do this... gems are designed to be used as libraries... not as applications on their own (investigate your distros application package system for that type of thing). Plus, you cannot assume your gem will only be used "once"... in theory several projects/applications could include your gem, and while there maybe some specifics to your gem that preclude it to something that could be globally configured... you still wouldn't want to do that because of other architecture concerns such as developing/configuring your application to work in different phase environments (dev/test/stage/production). The best case you could end up in is just noting howto create the /etc/ config files in the README and include a utility application to prompt the user for the values.



回答2:

2015-11-11 Here is the situation: RubyGems supports the pre and post install/uninstall hooks as extensions to the gem command. In other words these hooks apply to all gems that are installed and are not meant to be customised in a specific gem. They are invoked in a file called operating_system.rb usually found in /usr/lib64/ruby/2.2.0/rubygems; or whatever location and version Ruby is installed. The hooks are employed thus:

# /usr/lib/ruby/x.y.z./rubygems/operating_system.rb
Gem.pre_install do | installer |
  # do whatever
end

Gem.pre_uninstall do | installer |
  # do whatever
end

Gem.post_install do | installer |
  # do whatever
end
. . .

Going deeper into the API documentation it appears that to employ external activities specific to a gem one has plugins available. See: http://guides.rubygems.org/plugins/#executablehooks and https://github.com/rvm/executable-hooks as an example. However, these all seem to affect the RubyGem application generally rather than one gem specifically. And such plugins need be installed as gems themselves to have effect.

It seems to me that gem specific pre and post install hooks are a security issue. Someone installing a system level Gem has by definition root privilege and allowing RubyGem to perform arbitrary actions outside of simply installing a library has obvious security implications.

I am checking with the Ruby folks on this (2015-11-10). It may be that these hooks are only for the use of people installing RubyGem itself on different platforms.

RubyGems now (2015) supports pre_install() and post_install() hooks as methods which take an &block as their arguments. Presumably you can do anything you want in either of these providing that you do not return false from either. Returning nil is OK but a false return will abort the gem install.



回答3:

You should not want/need to do this... gems are designed to be used as libraries... not as applications on their own (investigate your distros application package system for that type of thing).

You know that. And I know that. But "they" don't know that. For many moons, the regular queries and comments were: "Is there a gem?" "Can this be installed as a gem?" "Why don't you make a gem?" "I didn't install this because it's not a gem."

Right or not, desirable or not, Joe Rubyist expects everything to be gemified. Only old schoolers are familiar with and seem to tolerate "ruby setup.rb" type deals.

Anyway, my application really is a standalone application; I can hardly imagine anyone including this like a library. Maybe as part of a collection of applications, but... usage as a library seems pretty far-fetched, but if that day should ever come, I'll cross that bridge when I get to it (to help people with any conflicts which inclusion might bring).

And there is no "dev/test/stage/prod" distinction. It's a Plain Old App, you run it from command line.

Anyway, thanks for your comments, at least my assumptions are affirmed in that the Rubygems system doesn't provide a way to do this.