I was working on building the mysql ruby gem. My mysql install is in a non-standard location. I could get the gem to build with syntax like:
gem install mysql -- --with-mysql-config=/path/to/bin/mysql_config
However, I noticed that the resulting library did not embed the path to the mysql library, ldd on the mysql.so indicated:
libmysqlclient.so.16 => not found
I did not want to have to fiddle with setting an LD_LIBRARY_PATH at runtime. The way to address this is to pass -R or -rpath to the linker at compile time to embed the path to the library. The mysql gem uses the standard extconf.rb to build a Makefile to build the library. extconf.rb uses the standard Ruby mkmf library to do the heavy lifting. Thanks to the woeful lack of documentation for mkmf it took me several hours to figure out how to convince mkmf to include the proper option in the compiler flags. The answer is:
gem install mysql -- --with-mysql-config=/path/to/bin/mysql_config --with-dldflags="-Wl,-rpath,/path/to/lib/mysql"
--with-dldflags appends anything you specify to the DLDFLAGS variable in the generated Makefile. FYI, --with-ldflags overwrites DLDFLAGS with what you specify, possibly wiping out other linker flags you want to keep. Also FYI, the -Wl,-rpath,etc. syntax is required to pass the linker option through the compiler.
ldd now shows that the path is embeded in the resulting mysql.so:
libmysqlclient.so.16 => /path/to/lib/mysql/libmysqlclient.so.16 (0x00002ad5e81d1000)
Friday, April 24, 2009
Thursday, March 12, 2009
Speaking of Perl, Ruby and sorting, sort in both Perl and Ruby allow you to specify a code block to implement your own arbitrary sorting routine. Perl's documentation shows you how you can define this as a subroutine and just reference the subroutine when you call sort. This is handy both for re-use and when your sort routine is complex and doesn't easily fit on one line. Ruby's sort documentation? Eh, no mention of such a thing.
In fact it is possible, but delves into a whole area of Ruby that is somewhat under-documented. The trick is that sort wants a code block, but code blocks are not first class entities. You can't name and reference a code block. However, Ruby has a couple of similar entities, Proc and lambda, that can be converted to/from code blocks and can be named and referenced. The unary ampersand operator will convert a Proc or lambda to a code block. The syntax works like this:
names = [
{:fname => 'John', :lname => 'Smith'},
{:fname => 'Jane', :lname => 'Smith'} ]
sorter = lambda do |a,b|
[a[:lname], a[:fname]] <=> [b[:lname], b[:fname]]
end
names.sort(&sorter)
In fact it is possible, but delves into a whole area of Ruby that is somewhat under-documented. The trick is that sort wants a code block, but code blocks are not first class entities. You can't name and reference a code block. However, Ruby has a couple of similar entities, Proc and lambda, that can be converted to/from code blocks and can be named and referenced. The unary ampersand operator will convert a Proc or lambda to a code block. The syntax works like this:
names = [
{:fname => 'John', :lname => 'Smith'},
{:fname => 'Jane', :lname => 'Smith'} ]
sorter = lambda do |a,b|
[a[:lname], a[:fname]] <=> [b[:lname], b[:fname]]
end
names.sort(&sorter)
Wednesday, March 11, 2009
When sorting complex structures in Perl is is common to use syntax like:
sort { $lname{$a} <=> $lname{$b} || $fname{$a} <=> $fname{$b} } @names
The Perl sort documentation lists examples with this syntax. True to form the Ruby sort documentation doesn't show examples of anything that complex. Best I can tell anything like this doesn't work in Ruby:
a <=> b || c <=> d
Any way I write that I get back the result of the first comparison, even if the result is zero (which should trigger a fall-through to the second comparison).
Since Ruby's Array implements <=> you can achieve the desired result with:
[a, c] <=> [b, d]
sort { $lname{$a} <=> $lname{$b} || $fname{$a} <=> $fname{$b} } @names
The Perl sort documentation lists examples with this syntax. True to form the Ruby sort documentation doesn't show examples of anything that complex. Best I can tell anything like this doesn't work in Ruby:
a <=> b || c <=> d
Any way I write that I get back the result of the first comparison, even if the result is zero (which should trigger a fall-through to the second comparison).
Since Ruby's Array implements <=> you can achieve the desired result with:
[a, c] <=> [b, d]
Wednesday, March 04, 2009
A couple of MacPorts errors I just encountered:
Error: Unable to execute port: can't read "frameworks_dir": no such variable
I had version 1.6 and it seems the recommendation to fix this is to update to 1.7 (via port selfupdate). I started port in interactive mode, ran selfupdate, then tried my install again and got:
Error: Unable to open port: can't read "porturl": no such variable
I wasn't sure if it was necessary, so I ran 'sync' at this point. The install then failed with:
Error: Unable to execute port: can't read "PortInfo(name)": no such element in array
Couldn't find any info about that online, so on a lark I exited port and restarted it, after which the install proceeded.
Error: Unable to execute port: can't read "frameworks_dir": no such variable
I had version 1.6 and it seems the recommendation to fix this is to update to 1.7 (via port selfupdate). I started port in interactive mode, ran selfupdate, then tried my install again and got:
Error: Unable to open port: can't read "porturl": no such variable
I wasn't sure if it was necessary, so I ran 'sync' at this point. The install then failed with:
Error: Unable to execute port: can't read "PortInfo(name)": no such element in array
Couldn't find any info about that online, so on a lark I exited port and restarted it, after which the install proceeded.
Thursday, January 15, 2009
It's a mystery to me why the FreeBSD folks don't publish this better (for example, a mention on http://www.freebsd.org/security/ doesn't seem unreasonable), but FreeBSD has an easy to use system for updating the base system:
# freebsd-update fetch
Review the changes to be applied, then
# freebsd-update install
If there's a new kernel in there then you should reboot. That's it. Not quite sure when this was fully integrated into the base OS, I'm only an occasional FreeBSD user, you used to have to install a few ports to get this working.
Even their official security advisories don't mention this, instead referring to PITA methods of patching and building from source. I installed the OS via pre-built binaries, why would I then update by patching the source? Sigh.
# freebsd-update fetch
Review the changes to be applied, then
# freebsd-update install
If there's a new kernel in there then you should reboot. That's it. Not quite sure when this was fully integrated into the base OS, I'm only an occasional FreeBSD user, you used to have to install a few ports to get this working.
Even their official security advisories don't mention this, instead referring to PITA methods of patching and building from source. I installed the OS via pre-built binaries, why would I then update by patching the source? Sigh.
Tuesday, January 06, 2009
Went looking around today for a way to generate charts/graphs in my Rails apps. Wow are there a lot of choices.
The executive summary is that I'm going to use the first Open Flash Chart plugin listed. I'm adding charts mainly for the "wow, neat" effect and the Flash charts max out that aspect. It seems like I might be able to work around the problems with printing. My second choice would probably be the ProtoChart Javascript library.
Plugins that generate images and/or SVG files:
Gruff
Scruffy
There are a couple of problems with these. Both use the RMagick library to generate images. RMagick is a Ruby wrapper around ImageMagick. So you're stuck with installing native dependencies (ImageMagick and all its dependencies) outside of Rails/Gems. And because you're providing the chart as a separate file you have to deal with sending the client a URL for the chart that comes back to your controller to generate the chart. There are probably neat Rails ways to handle that cleanly, but neither plugin seems to offer any best practices in their docs. I've also heard rumors that the RMagick/ImageMagick combo leaks memory like a sieve, but can't confirm that.
Plugins that use the Google Chart API:
Googlecharts
gchartrb
Google Charts on Rails
These all leave you dependent on connectivity and latency to Google.
Plugins that generate graphs using CSS/HTML:
css_graphs
There's only so much you can do in pure CSS/HTML, so this approach is fairly limited. If your needs are confined to basic bar charts this is a minimal-headache approach.
JavaScript libraries, particularly ones that work with Prototype since it is included with Rails:
Plotr
Flotr
ProtoChart
These are all pure JavaScript, so you're stuck dinking around in that instead of Ruby. There's a Rails wrapper for Plotr:
Chartr
Development of the JavaScript libraries and the Ruby library all seems largely stalled.
Plugins that generate Flash charts:
Wrappers for Open Flash Chart:
Open Flash Chart II Plugin for Ruby on Rails
Open Flash Chart Lazy
OFC2 4 Rails
These flash charts are the most visually interesting, as they are often animated and interactive, doing various cute (and maybe useful) things on mouse-over, etc. However, they leave you dependent on the client supporting/enabling Flash. It is also difficult/impossible to print the chart. You might also have the same issues as the image/SVG charts of having to generate a unique URL for the chart, although the author of the first plugin listed has a blog post that shows how to handle that in a very clean, Rails-like fashion.
Wrapper for XML/SWF:
ZiYa
Wrapper for amCharts:
Ambling
XML/SWF and amCharts are both demoware so I did not pursue these options.
The executive summary is that I'm going to use the first Open Flash Chart plugin listed. I'm adding charts mainly for the "wow, neat" effect and the Flash charts max out that aspect. It seems like I might be able to work around the problems with printing. My second choice would probably be the ProtoChart Javascript library.
Plugins that generate images and/or SVG files:
Gruff
Scruffy
There are a couple of problems with these. Both use the RMagick library to generate images. RMagick is a Ruby wrapper around ImageMagick. So you're stuck with installing native dependencies (ImageMagick and all its dependencies) outside of Rails/Gems. And because you're providing the chart as a separate file you have to deal with sending the client a URL for the chart that comes back to your controller to generate the chart. There are probably neat Rails ways to handle that cleanly, but neither plugin seems to offer any best practices in their docs. I've also heard rumors that the RMagick/ImageMagick combo leaks memory like a sieve, but can't confirm that.
Plugins that use the Google Chart API:
Googlecharts
gchartrb
Google Charts on Rails
These all leave you dependent on connectivity and latency to Google.
Plugins that generate graphs using CSS/HTML:
css_graphs
There's only so much you can do in pure CSS/HTML, so this approach is fairly limited. If your needs are confined to basic bar charts this is a minimal-headache approach.
JavaScript libraries, particularly ones that work with Prototype since it is included with Rails:
Plotr
Flotr
ProtoChart
These are all pure JavaScript, so you're stuck dinking around in that instead of Ruby. There's a Rails wrapper for Plotr:
Chartr
Development of the JavaScript libraries and the Ruby library all seems largely stalled.
Plugins that generate Flash charts:
Wrappers for Open Flash Chart:
Open Flash Chart II Plugin for Ruby on Rails
Open Flash Chart Lazy
OFC2 4 Rails
These flash charts are the most visually interesting, as they are often animated and interactive, doing various cute (and maybe useful) things on mouse-over, etc. However, they leave you dependent on the client supporting/enabling Flash. It is also difficult/impossible to print the chart. You might also have the same issues as the image/SVG charts of having to generate a unique URL for the chart, although the author of the first plugin listed has a blog post that shows how to handle that in a very clean, Rails-like fashion.
Wrapper for XML/SWF:
ZiYa
Wrapper for amCharts:
Ambling
XML/SWF and amCharts are both demoware so I did not pursue these options.
Friday, June 20, 2008
I haven't dug around in the commit logs enough to figure out when support was added (looks like it has been there a while), but with Rails 2.1 the documentation caught up and ActiveRecord::Serialization#to_xml supports nested includes. Note that the syntax of the hash that :include is expecting is different from the syntax of the :include hash for find, for whatever reason, so check the docs.
Here's the commit that added the documentation: http://dev.rubyonrails.org/changeset/9093
Until api.rubyonrails.com is updated with the 2.1 API docs you can view them here: http://caboo.se/doc/classes/ActiveRecord/Serialization.html
Here's the commit that added the documentation: http://dev.rubyonrails.org/changeset/9093
Until api.rubyonrails.com is updated with the 2.1 API docs you can view them here: http://caboo.se/doc/classes/ActiveRecord/Serialization.html
Monday, June 16, 2008
I tried to install RHEL 5 x86_64 in a VMware Server 2.0 Beta 2 virtual machine. The host system has a 64 bit CPU and the virtual machine had been configured for a 64 bit OS. Nevertheless the installer failed with:
Some poking around turned up this VMware document. In short I had to go into the BIOS on my host system and enable Virtualization Technology. On my Dell server that was disabled by default.
Your CPU does not support long mode. Use a 32 bit distribution
Some poking around turned up this VMware document. In short I had to go into the BIOS on my host system and enable Virtualization Technology. On my Dell server that was disabled by default.
I moved my Cacti install from one host to another. After dealing with some other issues the poller seemed to be running more-or-less alright. But the rrd files in the rra directory weren't updating and the graphs weren't displaying. There weren't any obvious errors in cacti.log. Looking around on the web folks mostly pointed to issues with file permissions on the rrd files or the rra directory. Sure enough, I had that problem (in the process of moving I upgraded to a new version of Cacti and switched to Dag's RPM package, which uses a 'cacti' user with a different UID than the 'cactiuser' user that my previous package had used). So I fixed that and waiting for the poller to run again, but still no updates to the rra directory. I thought I'd check that rrdtool was working, so I tried to dump out one of the rrd files:
Indeed, in this move I had gone from RHEL 4 x86 to RHEL 5 x86_64. I suppose I could have gone back to the old machine and exported the data and blah blah, but I just blew away all of the files in the rra directory and the next time the poller ran it created new rrds and all seems happy now.
% rrdtool dump /var/www/cacti/rra/blah.rrd
ERROR: This RRD was created on other architecture
Indeed, in this move I had gone from RHEL 4 x86 to RHEL 5 x86_64. I suppose I could have gone back to the old machine and exported the data and blah blah, but I just blew away all of the files in the rra directory and the next time the poller ran it created new rrds and all seems happy now.
I had to install Firefox on a Red Hat Enterprise Linux 5 server to run the VMware Server web UI. I did a 'yum install firefox', which pulled in a bunch of dependencies. But firefox wouldn't start:
As these things go, of course fontconfig was installed. So I did a 'yum list | grep font' and more-or-less started randomly installing packages until Firefox worked. The one that seemed to do the trick was xorg-x11-fonts-Type1
% firefox
No fonts found; this probably means that the fontconfig library is not correctly configured. You may need to edit the fonts.conf configuration file. More information about fontconfig can be bound in the fontconfig(3) manual page and on http://fontconfig.org
As these things go, of course fontconfig was installed. So I did a 'yum list | grep font' and more-or-less started randomly installing packages until Firefox worked. The one that seemed to do the trick was xorg-x11-fonts-Type1
Monday, June 02, 2008
I'm working on enhancing nVentory to meet my employer's needs for an operations database. I'm learning Ruby on Rails in the process and encountering a number of situations that seem poorly documented online. I'm going to try to capture some of these here for posterity. I'm starting this somewhat after the fact (having been working on this project for 5 or 6 weeks now), so these aren't necessarily in the order I encountered them.
First up, problems with connecting to an LDAP server. I started with the snippit of code in the "How is it then used?" section of http://wiki.rubyonrails.org/rails/pages/HowtoAuthenticateWithRubyNetLdap. Since the LDAP servers I'm talking to are Microsoft Active Directory servers I figured I'd automagically figure out which server to talk to via the DNS SRV records that AD publishes:
That was failing with an exception:
Unfortunately the code in Net::LDAP eats the real exception and throws its own generic "no connection to server" exception in the face of any problems creating the TCP connection to the server. I suppose I could have used the debugger to break on the rescue statement, but I just hacked in a "puts" into the library to see that the real exception was:
Bah humbug. ldapsrv.target is a Resolv::DNS::Name, which has a to_s method. So change the Net::LDAP.new to:
First up, problems with connecting to an LDAP server. I started with the snippit of code in the "How is it then used?" section of http://wiki.rubyonrails.org/rails/pages/HowtoAuthenticateWithRubyNetLdap. Since the LDAP servers I'm talking to are Microsoft Active Directory servers I figured I'd automagically figure out which server to talk to via the DNS SRV records that AD publishes:
require 'resolv'
require 'net/ldap'
res = Resolv::DNS::new()
ldapsrv = res.getresource('_ldap._tcp.my.domain', Resolv::DNS::Resource::IN::SRV)
ldap = Net::LDAP.new :host => ldapsrv.target, ...
That was failing with an exception:
Net::LDAP::LdapError (no connection to server):
/Library/Ruby/Gems/1.8/gems/ruby-net-ldap-0.0.4/lib/net/ldap.rb:1021:in `initialize'
Unfortunately the code in Net::LDAP eats the real exception and throws its own generic "no connection to server" exception in the face of any problems creating the TCP connection to the server. I suppose I could have used the debugger to break on the rescue statement, but I just hacked in a "puts" into the library to see that the real exception was:
can't convert Resolv::DNS::Name into String
Bah humbug. ldapsrv.target is a Resolv::DNS::Name, which has a to_s method. So change the Net::LDAP.new to:
ldap = Net::LDAP.new :host => ldapsrv.target.to_s, ...
Sunday, December 26, 2004
Upgraded to Fedora Core 3? yum-arch tells you it has been deprecated? yum won't read your repositories anymore, complaining that repomd.xml doesn't exist? You've been to http://linux.duke.edu/projects/metadata and it doesn't tell you what has replaced yum-arch? Sigh, me too. The magic answer is 'createrepo', there's an RPM for it that comes with FC3.
Saturday, November 06, 2004
Got myself a shiny new Nokia 6820 from AT&T Wireless. One of the attractions was the possibility of Internet access using Bluetooth from my PowerBook to the phone and GPRS/EDGE from the phone to the big I. It took some poking around but it works and seems fairly speedy. This page has a set of instructions for a different phone that apply pretty well. I'm using the same "Nokia GPRS CID1" script that he's using. In the PPP setup I left Account Name and Password blank and put "proxy" into the Telephone Number field. "proxy" is the default APN for AT&T Wireless.
Wednesday, July 21, 2004
Notes to myself about how to use GPG:
Export my own key for sending to others:
gpg --armor --export [my name]
Import another person's key:
gpg --import [key file]
or
gpg --keyserver [server] --search [their name]
Then sign their key and indicate that I trust it (GPG will prompt for degrees of trust):
gpg --edit-key [their name]
sign
trust
save
Export my own key for sending to others:
gpg --armor --export [my name]
Import another person's key:
gpg --import [key file]
or
gpg --keyserver [server] --search [their name]
Then sign their key and indicate that I trust it (GPG will prompt for degrees of trust):
gpg --edit-key [their name]
sign
trust
save
Wednesday, October 01, 2003
Have you upgraded OpenSSH to 3.7.1p2 because of the security problems, do you have sshd configured to use PAM, and now your Windows clients can't connect? Hey, what a coincidence, me too.
If you look a little closer at the dialog box that the Windows client pops up when you do a Quick Connect, you'll notice that there is a pull down menu at the bottom labeled Authentication Method. It defaults to Password. Try switching it to Keyboard Interactive and you should be able to log in.
It seems that the best fix for this is to edit the Quick Connect profile and add Keyboard Interactive to the acceptable authentication methods. Then in the Quick Connect dialog box choose <Profile Settings> for the Authentication Method. Connect and then choose Save Settings.
If you look a little closer at the dialog box that the Windows client pops up when you do a Quick Connect, you'll notice that there is a pull down menu at the bottom labeled Authentication Method. It defaults to Password. Try switching it to Keyboard Interactive and you should be able to log in.
It seems that the best fix for this is to edit the Quick Connect profile and add Keyboard Interactive to the acceptable authentication methods. Then in the Quick Connect dialog box choose <Profile Settings> for the Authentication Method. Connect and then choose Save Settings.
Monday, August 25, 2003
Want to make sendmail's -bP flag work? What's -bP do, you ask? It prints the size of your mail queue (rather like the last line of mailq (aka sendmail -bp)) without printing all of the entries in the mail queue.
First make sure your sendmail was compiled with shared memory support. Run 'sendmail -bv -d0.12 root' and look for SM_CONF_SHM. (Documented here)
Then add the following to your sendmail.m4:
define(`confSHARED_MEMORY_KEY', `42')
The value is arbitrary, it just can't be 0 (zero). If you happen to be running more than one copy of sendmail on your box with different queues, each sendmail config file should use a different value. (Documented (vaguely) here) Rebuild your sendmail.cf, restart sendmail, and -bP should work.
First make sure your sendmail was compiled with shared memory support. Run 'sendmail -bv -d0.12 root' and look for SM_CONF_SHM. (Documented here)
Then add the following to your sendmail.m4:
define(`confSHARED_MEMORY_KEY', `42')
The value is arbitrary, it just can't be 0 (zero). If you happen to be running more than one copy of sendmail on your box with different queues, each sendmail config file should use a different value. (Documented (vaguely) here) Rebuild your sendmail.cf, restart sendmail, and -bP should work.
Subscribe to:
Posts (Atom)