Adobe Air 2.5.1 GLIBC_2.7 error

Today I’ve tried to run Balsamiq Mockups on CentOS 5 and it failed to start with the following message:

Error loading the runtime (/lib/libc.so.6: version `GLIBC_2.7' not found (required by /opt/Adobe AIR/Versions/1.0/Resources/libcurl.so))

My laptop is subscribed to Adobe’s YUM repository and adobeair has been upgraded to 2.5.X on October 25. The new adobeair package has libcurl.so linked to glibc version 2.7 (CentOS 5 is shipping glibc 2.5):

[root@silver ~]# grep adobeair /var/log/yum.log*
/var/log/yum.log:Jun 30 12:15:19 Updated: adobeair-2.0.2-12610.i386
/var/log/yum.log:Aug 10 22:43:35 Updated: adobeair.i386 2.0.3-13070
/var/log/yum.log:Oct 06 00:29:04 Updated: adobeair.i386 2.0.4-13090
/var/log/yum.log:Oct 25 21:58:50 Updated: adobeair.i386 2.5.0-16600
/var/log/yum.log:Nov 16 22:30:39 Updated: adobeair.i386 2.5.1-17730

To solve this issue I’ve downgraded adobeair to the latest working version.

I’ve removed adobeair 2.5.1 from my laptop:

[root@silver ~]# yum remove adobeair

I’ve downloaded and installed adobeair 2.0.4-13090 from Adobe:

http://airdownload.adobe.com/air/lin/download/2.0.4/adobeair.i386.rpm

Some tweaks to Adobe’s repository settings (exclude=adobeair), disable adobeair updates untill Adobe will fix this issue:

# /etc/yum.repos.d/adobe-linux-i386.repo
[adobe-linux-i386]
name=Adobe Systems Incorporated
baseurl=http://linuxdownload.adobe.com/linux/i386/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-adobe-linux
exclude=adobeair

Count internal and external links in a page

Today I’ve readed the Webmaster Guidelines, in the “Design and content guidelines” section Google recommends to keep a resonable number of links in the page:

Keep the links on a given page to a reasonable number.

Mat Cutts talks about 100 links/page.

Hmm, how many links do I have in my pages ? I’ve made a simple Ruby script to count links in a page (Nokogiri, Domainatrix and Open-Uri made it trivial):

#!/usr/bin/env ruby
 
require "rubygems"
require "nokogiri"
require "open-uri"
require 'domainatrix'
 
url = ARGV.first
 
raise "*** Use: links_count <url>" unless url
 
domain = Domainatrix.parse(url)
 
int_links = 0
ext_links = 0
 
doc = Nokogiri::HTML(open(url).read)
doc.xpath("//a[@href]").each do |node|
  link = node.get_attribute('href')
 
  if link =~ %r{\Ahttp://}
    l = Domainatrix.parse(link)
    if l.public_suffix == domain.public_suffix and l.domain == domain.domain
      int_links += 1
    else
      ext_links += 1
      puts link
    end
  else
    int_links += 1
  end
end
 
puts ""
puts "*** internal links: #{int_links}"
puts "*** external links: #{ext_links}"
puts "*** total: #{int_links + ext_links}"

Now I can see how many internal/external links contains a page. Example for CNN.com:

[vitalie@silver ~]$ links_count.rb http://www.cnn.com
http://www.cnnmexico.com/
http://www.ireport.com/
http://www.time.com/time/world/article/0,8599,1997325,00.html
http://www.ireport.com/docs/DOC-459640?hpt=Mid
http://www.ireport.com/docs/DOC-459640?hpt=Mid
http://www.ireport.com/?hpt=Sbin
http://twitter.com/worldcupcnn
http://foursquare.com/cnn
http://movie-critics.ew.com/2010/06/16/psycho-turns-50-today/
http://www.cnngo.com/hong-kong/play/beyond-star-ferry-457619
http://www.cnngo.com/bangkok/play/spirited-competition-koh-samui-regatta-706618
http://www.ireport.com/?cnn=yes
http://www.turnerstoreonline.com/
http://www.cnntraveller.com
http://www.cnnchile.com
http://www.cnnmexico.com
http://cnn.joins.com/
http://www.cnn.co.jp/
http://www.cnnturk.com/
http://www.turner.com/
http://www.cnnmediainfo.com/
http://www.turner.com/careers/
 
*** internal links: 263
*** external links: 22
*** total: 285

SpamAssassin FH_DATE_PAST_20XX bug

Starting with January many I had many complaints from customers regarding legitimate mail marked as SPAM hosted on Plesk/SpamGuardian machines.

After a small investigation I’ve found the problems were from SpamAssassin’s FH_DATE_PAST_20XX rule bug that caused mails to receive a high score if date is past 2010-01-01.

http://wiki.apache.org/spamassassin/Rules/FH_DATE_PAST_20XX
https://issues.apache.org/SpamAssassin/show_bug.cgi?id=5852
https://issues.apache.org/SpamAssassin/show_bug.cgi?id=6269

I didn’t wanted to run sa-update, so I’ve created a config file to ignore this rule (I do love stability, so I’m more conservative :) ) :

[root@apollo ~]# cat /etc/mail/spamassassin/fh_date_past_20xx_fix.cf
# https://issues.apache.org/SpamAssassin/show_bug.cgi?id=6269
score FH_DATE_PAST_20XX 0.0

Speed up your website by compressing PNG images

Webpagetest.org is a great tool to learn how you can improve your website loading time (you should use it if you aren’t using it already).

Today after running a report I’ve seen that we had a large image on the home page that can be compressed to minimize loading time.

Smaller images means faster pages, faster pages means happy users :) . To compress images on Linux there are at least 2 alternatives:

OptiPNG: Advanced PNG Optimizer
OptiPNG is a PNG optimizer that recompresses image files to a smaller size, without losing any information. This program also converts external formats (BMP, GIF, PNM and TIFF) to optimized PNG, and performs PNG integrity checks and corrections.

Install optipng package from EPEL repository:

[root@silver ~]# yum install optipng
 
[...]
 
[root@silver ~]# optipng 
OptiPNG 0.6.2: Advanced PNG optimizer.
Copyright (C) 2001-2008 Cosmin Truta.
 
Type "optipng -h" for advanced help.
 
Synopsis:
    optipng [options] files ...
Files:
    Image files of type: PNG, BMP, GIF, PNM or TIFF
Basic options:
    -h, -help           show the advanced help
    -v                  verbose mode / show copyright, version and build info
    -o  <level>         optimization level (0-7)                default 2
    -i  <type>          interlace type (0-1)                    default <input>
    -k, -keep           keep a backup of the modified files
    -q, -quiet          quiet mode
Examples:
    optipng file.png                    (default speed)
    optipng -o5 file.png                (moderately slow)
    optipng -o7 file.png                (very slow)

Pngcrush
Pngcrush is an optimizer for PNG (Portable Network Graphics) files. It can be run from a commandline in an MSDOS window, or from a UNIX or LINUX commandline.

Its main purpose is to reduce the size of the PNG IDAT datastream by trying various compression levels an PNG filter methods. It also can be used to remove unwanted ancillary chunks, or to add certain chunks including gAMA, tRNS, iCCP, and textual chunks.

Install pngcrush from DAG’s repository:

[root@silver ~]# yum install pngcrush
 
[...]
 
[root@silver ~]# pngcrush --help
 
 | pngcrush 1.7.3
 |    Copyright (C) 1998-2002,2006-2009 Glenn Randers-Pehrson
 |    Copyright (C) 2005      Greg Roelofs
 | This is a free, open-source program.  Permission is irrevocably
 | granted to everyone to use this version of pngcrush without
 | payment of any fee.
 | Executable name is pngcrush
 | It was built with libpng version 1.2.40, and is
 | running with  libpng version 1.2.40 - September 10, 2009
 
 |    Copyright (C) 1998-2004,2006-2009 Glenn Randers-Pehrson,
 |    Copyright (C) 1996, 1997 Andreas Dilger,
 |    Copyright (C) 1995, Guy Eric Schalnat, Group 42 Inc.,
 | and zlib version 1.2.3.3, Copyright (C) 1998-2002 (or later),
 |    Jean-loup Gailly and Mark Adler.
 | It was compiled with gcc version 4.1.2 20080704 (Red Hat 4.1.2-46).
 
[...]
 
usage: pngcrush [options] infile.png outfile.png
       pngcrush -e ext [other options] files.png ...
       pngcrush -d dir [other options] files.png ...
options:
 
[...]

Now you can compress PNG images to reduce its size using command line:

[vitalie@silver ~]$ optipng -o7 example.png
[vitalie@silver ~]$ pngcrush -brute -e ".compressed.png"  *png

I’ve achieved 20% – 24% file size reduction after compression.

More on the subject:
Indopedia
Raymond.cc

MysqlProxy: No package ‘lua5.1′ found

Somehow my Lua rpm package missed the /usr/lib/pkgconfig/lua.pc file and MysqlProxy couldn’t detect Lua install:

[vitalie@silver tmp]$ rpmbuild -ta --define 'with_lua 1' mysql-proxy-0.6.0.tar.gz
 
[...]
 
checking for LUA... checking for LUA... configure: error: Package requirements (lua5.1 >= 5.1) were not met:
 
No package 'lua5.1' found
 
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
 
Alternatively, you may set the environment variables LUA_CFLAGS
and LUA_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.

The solution was to specify LUA_CFLAGS and LUA_LIBS variables:

[vitalie@silver tmp]$ LUA_CFLAGS="-I/usr/include" LUA_LIBS="-llua -lm -ldl" rpmbuild -ta --define 'with_lua 1' mysql-proxy-0.6.0.tar.gz
 
[...]
 
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Requires: libc.so.6()(64bit) libc.so.6(GLIBC_2.2.5)(64bit) libc.so.6(GLIBC_2.3)(64bit) libc.so.6(GLIBC_2.3.4)(64bit) libc.so.6(GLIBC_2.4)(64bit) libdl.so.2()(64bit) libdl.so.2(GLIBC_2.2.5)(64bit) libevent-1.1a.so.1()(64bit) libglib-2.0.so.0()(64bit) libm.so.6()(64bit) libm.so.6(GLIBC_2.2.5)(64bit) rtld(GNU_HASH)
Processing files: mysql-proxy-debuginfo-0.6.0-0
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/vitalie/rpmbuild/tmp/mysql-proxy-0.6.0-0-root
Wrote: /home/vitalie/rpmbuild/SRPMS/mysql-proxy-0.6.0-0.src.rpm
Wrote: /home/vitalie/rpmbuild/RPMS/x86_64/mysql-proxy-0.6.0-0.x86_64.rpm
Wrote: /home/vitalie/rpmbuild/RPMS/x86_64/mysql-proxy-debuginfo-0.6.0-0.x86_64.rpm
Executing(%clean): /bin/sh -e /home/vitalie/rpmbuild/tmp/rpm-tmp.9187
 
[...]

References:

Swappiness and responsiveness on Linux desktops

Doing a lots of db import/export/migration tasks on my Linux notebook on large DB tables, I’ve seen slow responsiveness from the system. After a small investigation I’ve seen that my OS is swapping out too much causing performance degradation and making my system unusable.

By default Linux kernel is configured for server environments. One important parameter that should be considered when using Linux as desktop is vm.swappines, by default it’s value is 60.

That’s fine for a server as it swaps out memory to disk aggressively to release it for active processes, but on desktops this value is to high, the recommended value is 10 to allow the system to be more responsive.

[root@silver ~]# tail -2 /etc/sysctl.conf
# desktop settings
vm.swappiness = 10

More details:
Ubuntu Swap Faq
Optimizing Desktop Performance, Part I
Optimizing Desktop Performance, Part II
Optimizing Desktop Performance, Part III

Howto install RMagick 2 on CentOS/RHEL 5

Installing RMagick 2 on CentOS/RHEL 5 it’s not that hard, you just need to install ImageMagick newer than 6.3.5 (CentOS/RHEL 5 is shipping ImageMagick 6.2.8) and that’s the hardest part of the job.

[root@silver ~]# gem install rmagick
Building native extensions.  This could take a while...
ERROR:  Error installing rmagick:
        ERROR: Failed to build gem native extension.
 
/usr/local/bin/ruby extconf.rb
checking for Ruby version >= 1.8.5... yes
checking for gcc... yes
checking for Magick-config... yes
checking for ImageMagick version >= 6.3.5... no
Can't install RMagick 2.12.2. You must have ImageMagick 6.3.5 or later.

I’ve tried to avoid ImageMagick upgrade and to install RMagick 1, but RMagick 1 failed to install with a strange compile error, probably because the gcc compliler shipped with CentOS/RHEL 5 is too new for version 1.

I didn’t wanted to patch RMagick 1, neither to install from sources (I do prefer RPM packages). So, I’ve decided to upgrade ImageMagick library to satisfy RMagick 2 requirements.

Subscribe your system to the following repositories:

Install the following packages:

[root@silver ~]# yum --enablerepo=epel --enablerepo=rpmforge --enablerepo=centosplus install djvulibre-devel libwmf-devel jasper-devel libtool-ltdl-devel librsvg2-devel openexr-devel graphviz-devel gcc gcc-c++ ghostscript freetype-devel libjpeg-devel libpng-devel giflib-devel libwmf-devel libexif-devel libtiff-devel

Add “–noplugins” if you are using “yum-priorities”, or it will fail to install packages.

Download ImageMagick.spec to your SPECS directory and ImageMagick-6.5.7-0.tar.bz2 to SOURCES directory and then rebuild the rpm using rpmbuild:

[root@silver SPECS]# rpmbuild -ba ImageMagick.spec
 
[...]

Or just grab the source RPM from here:
http://red.penguin.ro/SRPMS/ImageMagick-6.5.7-0.src.rpm

and build it:

[root@silver ~]# rpmbuild --rebuild ImageMagick-6.5.7-0.src.rpm 
Installing ImageMagick-6.5.7-0.src.rpm
warning: user vitalie does not exist - using root
warning: group vitalie does not exist - using root
warning: user vitalie does not exist - using root
warning: group vitalie does not exist - using root
Executing(%prep): /bin/sh -e /home/worf/rpmbuild/tmp/rpm-tmp.11936
+ umask 022
+ cd /home/worf/rpmbuild/BUILD
+ LANG=C
+ export LANG
+ unset DISPLAY
+ cd /home/worf/rpmbuild/BUILD
+ rm -rf ImageMagick-6.5.7-0
+ /usr/bin/bzip2 -dc /home/worf/rpmbuild/SOURCES/ImageMagick-6.5.7-0.tar.bz2
+ tar -xf -
 
[...]
 
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Requires: /bin/sh ImageMagick-c++ = 6.5.7-0 ImageMagick-devel = 6.5.7-0 libMagick++.so.2()(64bit)
Processing files: ImageMagick-debuginfo-6.5.7-0
Provides: Magick.so.debug()(64bit) analyze.so.debug()(64bit) art.so.debug()(64bit) avi.so.debug()(64bit) avs.so.debug()(64bit) bmp.so.debug()(64bit) braille.so.debug()(64bit) cals.so.debug()(64bit) caption.so.debug()(64bit) cin.so.debug()(64bit) cip.so.debug()(64bit) clip.so.debug()(64bit) cmyk.so.debug()(64bit) cut.so.debug()(64bit) dcm.so.debug()(64bit) dds.so.debug()(64bit) dib.so.debug()(64bit) djvu.so.debug()(64bit) dng.so.debug()(64bit) dot.so.debug()(64bit) dpx.so.debug()(64bit) ept.so.debug()(64bit) fax.so.debug()(64bit) fits.so.debug()(64bit) gif.so.debug()(64bit) gradient.so.debug()(64bit) gray.so.debug()(64bit) hald.so.debug()(64bit) histogram.so.debug()(64bit) hrz.so.debug()(64bit) html.so.debug()(64bit) icon.so.debug()(64bit) info.so.debug()(64bit) inline.so.debug()(64bit) ipl.so.debug()(64bit) jp2.so.debug()(64bit) jpeg.so.debug()(64bit) label.so.debug()(64bit) libMagick++.so.2.0.0.debug()(64bit) libMagickCore.so.2.0.0.debug()(64bit) libMagickWand.so.2.0.0.debug()(64bit) magick.so.debug()(64bit) map.so.debug()(64bit) mat.so.debug()(64bit) matte.so.debug()(64bit) meta.so.debug()(64bit) miff.so.debug()(64bit) mono.so.debug()(64bit) mpc.so.debug()(64bit) mpeg.so.debug()(64bit) mpr.so.debug()(64bit) msl.so.debug()(64bit) mtv.so.debug()(64bit) mvg.so.debug()(64bit) null.so.debug()(64bit) otb.so.debug()(64bit) palm.so.debug()(64bit) pattern.so.debug()(64bit) pcd.so.debug()(64bit) pcl.so.debug()(64bit) pcx.so.debug()(64bit) pdb.so.debug()(64bit) pdf.so.debug()(64bit) pict.so.debug()(64bit) pix.so.debug()(64bit) plasma.so.debug()(64bit) png.so.debug()(64bit) pnm.so.debug()(64bit) preview.so.debug()(64bit) ps.so.debug()(64bit) ps2.so.debug()(64bit) ps3.so.debug()(64bit) psd.so.debug()(64bit) pwp.so.debug()(64bit) raw.so.debug()(64bit) rgb.so.debug()(64bit) rla.so.debug()(64bit) rle.so.debug()(64bit) scr.so.debug()(64bit) sct.so.debug()(64bit) sfw.so.debug()(64bit) sgi.so.debug()(64bit) stegano.so.debug()(64bit) sun.so.debug()(64bit) svg.so.debug()(64bit) tga.so.debug()(64bit) thumbnail.so.debug()(64bit) tiff.so.debug()(64bit) tile.so.debug()(64bit) tim.so.debug()(64bit) ttf.so.debug()(64bit) txt.so.debug()(64bit) uil.so.debug()(64bit) url.so.debug()(64bit) uyvy.so.debug()(64bit) vicar.so.debug()(64bit) vid.so.debug()(64bit) viff.so.debug()(64bit) wbmp.so.debug()(64bit) wmf.so.debug()(64bit) wpg.so.debug()(64bit) x.so.debug()(64bit) xbm.so.debug()(64bit) xc.so.debug()(64bit) xcf.so.debug()(64bit) xpm.so.debug()(64bit) xps.so.debug()(64bit) xwd.so.debug()(64bit) ycbcr.so.debug()(64bit) yuv.so.debug()(64bit)
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/worf/rpmbuild/tmp/ImageMagick-6.5.7-0-root-root
Wrote: /home/worf/rpmbuild/RPMS/x86_64/ImageMagick-6.5.7-0.x86_64.rpm
Wrote: /home/worf/rpmbuild/RPMS/x86_64/ImageMagick-devel-6.5.7-0.x86_64.rpm
Wrote: /home/worf/rpmbuild/RPMS/x86_64/ImageMagick-doc-6.5.7-0.x86_64.rpm
Wrote: /home/worf/rpmbuild/RPMS/x86_64/ImageMagick-perl-6.5.7-0.x86_64.rpm
Wrote: /home/worf/rpmbuild/RPMS/x86_64/ImageMagick-c++-6.5.7-0.x86_64.rpm
Wrote: /home/worf/rpmbuild/RPMS/x86_64/ImageMagick-c++-devel-6.5.7-0.x86_64.rpm
Wrote: /home/worf/rpmbuild/RPMS/x86_64/ImageMagick-debuginfo-6.5.7-0.x86_64.rpm
Executing(%clean): /bin/sh -e /home/worf/rpmbuild/tmp/rpm-tmp.25482
+ umask 022
+ cd /home/worf/rpmbuild/BUILD
+ cd ImageMagick-6.5.7-0
+ rm -rf /home/worf/rpmbuild/tmp/ImageMagick-6.5.7-0-root-root
+ exit 0
Executing(--clean): /bin/sh -e /home/worf/rpmbuild/tmp/rpm-tmp.25482
+ umask 022
+ cd /home/worf/rpmbuild/BUILD
+ rm -rf ImageMagick-6.5.7-0
+ exit 0

Uninstall i386 ImageMagick libraries if you are on x86_64 system:

[root@silver ~]# rpm -qa | grep ImageMagick | grep -i i386 | xargs rpm -e

Install the new RPMs compiled in the previous steps:

[root@silver x86_64]# rpm -Uvh ImageMagick-6.5.7-0.x86_64.rpm ImageMagick-c++-6.5.7-0.x86_64.rpm ImageMagick-c++-devel-6.5.7-0.x86_64.rpm ImageMagick-devel-6.5.7-0.x86_64.rpm

Finally, install the RMagick 2 plugin:

[root@silver ~]# gem install rmagick --no-rdoc --no-ri
Building native extensions.  This could take a while...
Successfully installed rmagick-2.12.2
1 gem installed

Ruby Enterprise Edition 1.8.7 source RPM for CentOS5 / RHEL5

Ruby Enterprise Edition is a server-oriented friendly branch of Ruby which includes various enhancements:

* A copy-on-write friendly garbage collector. Phusion Passenger uses this, in combination with a technique called preforking, to reduce Ruby on Rails applications’ memory usage by 33% on average.
* An improved memory allocator called tcmalloc, which improves performance quite a bit.
* The ability to tweak garbage collector settings for maximum server performance, and the ability to inspect the garbage collector’s state. (RailsBench GC patch)
* The ability to dump stack traces for all running threads (caller_for_all_threads), making it easier for one to debug multithreaded Ruby web applications.

More on Ruby Enterprise Edition’s website:
http://www.rubyenterpriseedition.com/

Download source rpm:
ruby-enterprise-1.8.7-1.el5.src.rpm

Build rpm package using rpmbuild:

[vitalie@silver SRPMS]$ rpmbuild --rebuild --define 'dist el5' ruby-enterprise-1.8.7-1.el5.src.rpm 
Installing ruby-enterprise-1.8.7-1.el5.src.rpm
Executing(%prep): /bin/sh -e /home/vitalie/rpmbuild/tmp/rpm-tmp.89437
+ umask 022
+ cd /home/vitalie/rpmbuild/BUILD
+ LANG=C
+ export LANG
+ unset DISPLAY
+ cd /home/vitalie/rpmbuild/BUILD
+ rm -rf ruby-enterprise-1.8.7-20090928
+ /bin/gzip -dc /home/vitalie/rpmbuild/SOURCES/ruby-enterprise-1.8.7-20090928.tar.gz
+ tar -xf -
+ STATUS=0
+ '[' 0 -ne 0 ']'
+ cd ruby-enterprise-1.8.7-20090928
++ /usr/bin/id -u
+ '[' 500 = 0 ']'
++ /usr/bin/id -u
+ '[' 500 = 0 ']'
+ /bin/chmod -Rf a+rX,u+w,g-w,o-w .
+ exit 0
Executing(%build): /bin/sh -e /home/vitalie/rpmbuild/tmp/rpm-tmp.89437
+ umask 022
+ cd /home/vitalie/rpmbuild/BUILD
+ cd ruby-enterprise-1.8.7-20090928
+ LANG=C
+ export LANG
+ unset DISPLAY
+ ./installer --auto /usr/local --dont-install-useful-gems --destdir /home/vitalie/rpmbuild/tmp/ruby-enterprise-1.8.7-20090928-root-vitalie
 
[...]
 
Provides: ruby-enterprise(rubygems) = 1.3.2
Requires(interp): /bin/sh
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1 rpmlib(VersionedDependencies) <= 3.0.3-1
Requires(pre): /bin/sh
Requires: /usr/local/bin/ruby ruby-enterprise >= 1.8
Processing files: ruby-enterprise-debuginfo-1.8.7-1.el5
Provides: bigdecimal.so.debug()(64bit) bubblebabble.so.debug()(64bit) cparse.so.debug()(64bit) curses.so.debug()(64bit) dbm.so.debug()(64bit) digest.so.debug()(64bit) dl.so.debug()(64bit) etc.so.debug()(64bit) fcntl.so.debug()(64bit) gdbm.so.debug()(64bit) iconv.so.debug()(64bit) libtcmalloc_minimal.so.0.0.0.debug()(64bit) md5.so.debug()(64bit) nkf.so.debug()(64bit) openssl.so.debug()(64bit) pty.so.debug()(64bit) readline.so.debug()(64bit) rmd160.so.debug()(64bit) sdbm.so.debug()(64bit) sha1.so.debug()(64bit) sha2.so.debug()(64bit) socket.so.debug()(64bit) stringio.so.debug()(64bit) strscan.so.debug()(64bit) syck.so.debug()(64bit) syslog.so.debug()(64bit) thread.so.debug()(64bit) wait.so.debug()(64bit) zlib.so.debug()(64bit)
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/vitalie/rpmbuild/tmp/ruby-enterprise-1.8.7-20090928-root-vitalie
Wrote: /home/vitalie/rpmbuild/RPMS/x86_64/ruby-enterprise-1.8.7-1.el5.x86_64.rpm
Wrote: /home/vitalie/rpmbuild/RPMS/x86_64/ruby-enterprise-rubygems-1.3.2-1.el5.x86_64.rpm
Wrote: /home/vitalie/rpmbuild/RPMS/x86_64/ruby-enterprise-debuginfo-1.8.7-1.el5.x86_64.rpm
Executing(%clean): /bin/sh -e /home/vitalie/rpmbuild/tmp/rpm-tmp.76776
+ umask 022
+ cd /home/vitalie/rpmbuild/BUILD
+ cd ruby-enterprise-1.8.7-20090928
+ rm -rf /home/vitalie/rpmbuild/tmp/ruby-enterprise-1.8.7-20090928-root-vitalie
+ exit 0
Executing(--clean): /bin/sh -e /home/vitalie/rpmbuild/tmp/rpm-tmp.76776
+ umask 022
+ cd /home/vitalie/rpmbuild/BUILD
+ rm -rf ruby-enterprise-1.8.7-20090928
+ exit 0

Alternatively you can download just spec file and grab sources from the REE’s website:
ruby-enterprise.spec

acts_as_redis_counter plugin

I’ve just released acts_as_redis_counter plugin for Rails.

Description:

The acts_as_redis_counter plugin implements high performance counters using write-back strategy with Redis key-value database.

Enjoy it!
http://github.com/vitalie/acts_as_redis_counter

Easy Rails virtual hosts with mod_macro

Keeping a separate file for each virtual host in /etc/httpd/vhosts.d it’s clean and cool, but when you have many virtual hosts with same settings it’s a pain to keep them updated. We need a template system for Apache configurations and mod_macro module it’s a handy tool for this job.

Download module version suited for your Apache from:
http://www.cri.ensmp.fr/~coelho/mod_macro/

Ensure that you have httpd-devel package installed then untar archive and compile mod_macro module with apxs:

[root@silver tmp]# wget http://www.cri.ensmp.fr/~coelho/mod_macro/mod_macro-1.1.10.tar.bz2
 
[...]
 
[root@silver tmp]# tar xvfjp mod_macro-1.1.10.tar.bz2 
 
[...]
 
[root@silver tmp]# cd mod_macro-1.1.10
[root@silver mod_macro-1.1.10]# apxs -cia mod_macro.c 
/usr/lib64/apr-1/build/libtool --silent --mode=compile gcc -prefer-pic -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fno-strict-aliasing  -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -pthread -I/usr/include/httpd  -I/usr/include/apr-1   -I/usr/include/apr-1   -c -o mod_macro.lo mod_macro.c && touch mod_macro.slo
mod_macro.c: In function 'looks_like_an_argument':
mod_macro.c:316: warning: cast from pointer to integer of different size
mod_macro.c: In function 'say_it':
mod_macro.c:929: warning: cast from pointer to integer of different size
/usr/lib64/apr-1/build/libtool --silent --mode=link gcc -o mod_macro.la  -rpath /usr/lib64/httpd/modules -module -avoid-version    mod_macro.lo
/usr/lib64/httpd/build/instdso.sh SH_LIBTOOL='/usr/lib64/apr-1/build/libtool' mod_macro.la /usr/lib64/httpd/modules
/usr/lib64/apr-1/build/libtool --mode=install cp mod_macro.la /usr/lib64/httpd/modules/
cp .libs/mod_macro.so /usr/lib64/httpd/modules/mod_macro.so
cp .libs/mod_macro.lai /usr/lib64/httpd/modules/mod_macro.la
cp .libs/mod_macro.a /usr/lib64/httpd/modules/mod_macro.a
chmod 644 /usr/lib64/httpd/modules/mod_macro.a
ranlib /usr/lib64/httpd/modules/mod_macro.a
PATH="$PATH:/sbin" ldconfig -n /usr/lib64/httpd/modules
----------------------------------------------------------------------
Libraries have been installed in:
   /usr/lib64/httpd/modules
 
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,--rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'
 
See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
chmod 755 /usr/lib64/httpd/modules/mod_macro.so
[activating module `macro' in /etc/httpd/conf/httpd.conf]

Create a file that will keep your macros in Apache’s conf.d directory (example: _mod_macro.conf), conf.d files are executed after modules are loaded:

# /etc/httpd/conf.d/_mod_macro.conf
 
# RailsHost macro
<Macro RailsHost $host $dir>
  <VirtualHost *:80>
    ServerName www.$host
    ServerAlias $host
    DocumentRoot $dir/current/public
 
    CustomLog "logs/$host_access.log" combined
    ErrorLog "logs/$host_error.log"
 
    # Passenger settings
    RailsBaseURI /
    RailsMaxPoolSize 1
    RailsPoolIdleTime 3600
    RailsEnv production
 
    # Redirect example.com -> www.example.com
    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^www.$host
    RewriteRule ^/(.*) http://www.$host/$1 [R=301,L]
 
    # Check for maintenance file and redirect all requests
    RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
    RewriteCond %{SCRIPT_FILENAME} !maintenance.html
    RewriteCond %{SCRIPT_FILENAME} !^/images
    RewriteCond %{SCRIPT_FILENAME} !^/stylesheets
    RewriteCond %{SCRIPT_FILENAME} !^/javascripts
    RewriteRule ^.*$ /system/maintenance.html [L]
 
    ErrorDocument 404 $dir/current/public/404.html
    ErrorDocument 422 $dir/current/public/422.html
    ErrorDocument 500 $dir/current/public/500.html
 
    Use ModDeflate
    Use ModExpires
 
    <Directory $dir/current/public>
      Options FollowSymLinks
      AllowOverride None
      Order allow,deny
      Allow from all
    </Directory>
  </VirtualHost>
</Macro>
 
# ModDeflate macro
<Macro ModDeflate>
  <IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/plain
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/xml
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE application/xhtml+xml
    AddOutputFilterByType DEFLATE application/rss+xml
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/x-javascript
 
    BrowserMatch ^Mozilla/4 gzip-only-text/html
    BrowserMatch ^Mozilla/4\.0[678] no-gzip
    BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
  </IfModule>
</Macro>
 
# ModExpires macro
<Macro ModExpires>
  <IfModule mod_expires.c>
    ExpiresActive On
    <LocationMatch "^/(images|javascripts|stylesheets)">
      ExpiresDefault "access plus 1 year"
    </LocationMatch>
  </IfModule>
</Macro>

Append RailsHost macro calls to your httpd.conf to define your virtual hosts :

# /etc/httpd/conf/httpd.conf
 
[...]
 
Use RailsHost vhost1.com /data/virtualhosts/vhost1.com
Use RailsHost vhost2.com /data/virtualhosts/vhost2.com

Now, your Apache configuration looks much better and when it comes make changes to your configurations you’ll need to change just one macro.