Since late 2011, I've found myself doing a lot more Linux administration than Mac. In light of that, I am launching a new Linux blog that will have a lot of overlap with Command Line Mac.
Mostly for my own convenience, I'll be copying a lot of the Unix/Linux only posts over to the new blog. I'll still be posting here when I run across something interesting in the Mac world, but I expect the other blog to be much more active this year.
Saturday, February 25, 2012
Adventures with Airport Express
After the failure of my cable TV/Internet service last month, and the slow response of the cable company, I dumped cable in favor of satellite+DSL. It was an inconvenient process to say the least. When it was done, I needed to connect the satellite DVR to the wireless DSL router to enable additional features.
The DVR had a USB wireless adapter, but because of the location of router, the signal was not quite strong enough to make the connection work. I had a spare Airport Express and my first thought was to use it to extend the DSL router network. Before doing any research, I made manual changes to the Airport Express that rendered it a brick. Doh!
I found a helpful article at Apple Support that let me reset it to factory settings. Then, I finally did the research and found that the plain Express can't be used to extend a 2WIRE wireless router.
The next strategy was to set up a separate wireless network and plug the Airport Express into one of the wired ports on the router. The Airport Express provided a stronger signal that the 2WIRE and allowed me to connect the DVR to the Internet. The only modification I had to make from a basic configuration was to turn off network address translation (NAT) on the Airport Express to avoid a double NAT situation since the 2WIRE also provided NAT. The Airport Express actually detected the problem and made the suggestion when I connected to it with the Airport Utility. Apple really has some very nicely thought out software in their hardware.
The DVR had a USB wireless adapter, but because of the location of router, the signal was not quite strong enough to make the connection work. I had a spare Airport Express and my first thought was to use it to extend the DSL router network. Before doing any research, I made manual changes to the Airport Express that rendered it a brick. Doh!
I found a helpful article at Apple Support that let me reset it to factory settings. Then, I finally did the research and found that the plain Express can't be used to extend a 2WIRE wireless router.
The next strategy was to set up a separate wireless network and plug the Airport Express into one of the wired ports on the router. The Airport Express provided a stronger signal that the 2WIRE and allowed me to connect the DVR to the Internet. The only modification I had to make from a basic configuration was to turn off network address translation (NAT) on the Airport Express to avoid a double NAT situation since the 2WIRE also provided NAT. The Airport Express actually detected the problem and made the suggestion when I connected to it with the Airport Utility. Apple really has some very nicely thought out software in their hardware.
Thursday, November 17, 2011
Ruby: Sorting an array with multiple fields
I was working on a project today and needed to make some changes to the way an array on objects was sorted before being displayed on the screen. The main reason I even bothered to post this is to heap a little more praise on Ruby for working the way I expected it to work.
Here was my object (not tied to a database, just created for convenience):
I sorted them by concatenating the fields together and making the right comparisons. This only works because the first two fields, rank and shift, cannot be empty. Otherwise, a simple concatenation would create undesired results.
Sorting all fields ascending looks like this:
Here was my object (not tied to a database, just created for convenience):
class ForceI needed to sort an array of these objects by rank ascending, shift ascending, then promoted_on (date) descending.
attr_accessor :id
attr_accessor :last_name
attr_accessor :first_name
attr_accessor :rank
attr_accessor :shift
attr_accessor :promoted_on
attr_accessor :phone
attr_accessor :totalcount
end
I sorted them by concatenating the fields together and making the right comparisons. This only works because the first two fields, rank and shift, cannot be empty. Otherwise, a simple concatenation would create undesired results.
Sorting all fields ascending looks like this:
@forces = @forces.sort {|x,y| x.shift + x.rank + x.promoted_on.to_s <=> y.shift + y.rank + y.promoted_on.to_s}To sort the promoted_on field in descending order, reverse the x,y sides for that field:
@forces = @forces.sort {|x,y| x.shift + x.rank + y.promoted_on.to_s <=> y.shift + y.rank + x.promoted_on.to_s}No need for a special sort coding block. Ruby FTW!
Thursday, October 6, 2011
Sunday, September 18, 2011
The Chromium OS experiment
Google's Chromium OS
I downloaded a bootable ISO of the Google Chromium OS release candidate. Then, fired it up in VMware Player and took a look around. It appears to be based on OpenSUSE Linux 11.4. SUSE was one of the distributions I cut my teeth on in the Linux world. I always appreciated the 9 pound manual of documentation that came with it. Very helpful for beginners and a good reference to their tools.
I might have made a mistake when setting up the virtual machine because it complained of low memory right after booting. This could also explain the slow performance I experienced. The desktop itself is clean and appears to be optimized to run the Chrome web browser. There was a local word processing application, but I didn't get far enough to test it out, it was just too slow. I could not find a download link at Google, but I found one at a .eu domain. Maybe it was a pirated or tampered version. I am going to postpone further research until I am sure I have a good distribution.
Updated: Turns out Google doesn't provide an image or download of the OS itself, only the source code and compilation instructions. Also, the OS is based on Ubuntu, despite the build I got from Europe based on SUSE. ZD Net suggested that the running OS would be slow so I maybe I am not missing much at this stage of development. I don't want to pay for a Chromebook just to run Chrome. Another reason to keep this on hold for now.
I downloaded a bootable ISO of the Google Chromium OS release candidate. Then, fired it up in VMware Player and took a look around. It appears to be based on OpenSUSE Linux 11.4. SUSE was one of the distributions I cut my teeth on in the Linux world. I always appreciated the 9 pound manual of documentation that came with it. Very helpful for beginners and a good reference to their tools.
I might have made a mistake when setting up the virtual machine because it complained of low memory right after booting. This could also explain the slow performance I experienced. The desktop itself is clean and appears to be optimized to run the Chrome web browser. There was a local word processing application, but I didn't get far enough to test it out, it was just too slow. I could not find a download link at Google, but I found one at a .eu domain. Maybe it was a pirated or tampered version. I am going to postpone further research until I am sure I have a good distribution.
Updated: Turns out Google doesn't provide an image or download of the OS itself, only the source code and compilation instructions. Also, the OS is based on Ubuntu, despite the build I got from Europe based on SUSE. ZD Net suggested that the running OS would be slow so I maybe I am not missing much at this stage of development. I don't want to pay for a Chromebook just to run Chrome. Another reason to keep this on hold for now.
Wednesday, July 20, 2011
Getting by in Git
Git is the source code management system used for the Linux kernel and many other highly complex projects. It was written by Linux Torvalds after some controversy over the proprietary Bitkeeper program that used to manage the Linux kernel.
I've needed to upgrade my skills recently to use git in place of subversion because that is what my shop decided to use. I've moved all my Rails code into a remote git server and so far, so good.
One improvement is it has fewer "droppings" than subversion. There is no hidden .svn directory in each directory with source code. Only a single .git directory at the root of the project, plus a .gitignore file for files you don't want git to track.
Initialize project tracking
git init
Check out an existing project from remote server
git clone ssh://server/git/project
Add a file for git to track
git add
Add all files from this directory and below for git to track
git add .
Commit all files to local repository
git commit -a -m "message"
Undo changes to a file (re-check out from repository)
git checkout --
Pull files from remote repository and merge with local repository
git pull
Push files to remote repository (must commit first)
git push
Move file or directory to new location
git mv path destination
Remove file or directory from the working tree
git rm path
To create a remote repository from an existing project takes several steps
cd /tmp
git clone --bare /path/to/project (creates a /tmp/project.git directory)
scp project.git to remote server
cd /path/to/project
git remote add origin ssh://server/git/project
git config branch.master.remote origin
git config branch.master.merge refs/heads/master
I've needed to upgrade my skills recently to use git in place of subversion because that is what my shop decided to use. I've moved all my Rails code into a remote git server and so far, so good.
One improvement is it has fewer "droppings" than subversion. There is no hidden .svn directory in each directory with source code. Only a single .git directory at the root of the project, plus a .gitignore file for files you don't want git to track.
Initialize project tracking
git init
Check out an existing project from remote server
git clone ssh://server/git/project
Add a file for git to track
git add
Add all files from this directory and below for git to track
git add .
Commit all files to local repository
git commit -a -m "message"
Undo changes to a file (re-check out from repository)
git checkout --
Pull files from remote repository and merge with local repository
git pull
Push files to remote repository (must commit first)
git push
Move file or directory to new location
git mv path destination
Remove file or directory from the working tree
git rm path
To create a remote repository from an existing project takes several steps
cd /tmp
git clone --bare /path/to/project (creates a /tmp/project.git directory)
scp project.git to remote server
cd /path/to/project
git remote add origin ssh://server/git/project
git config branch.master.remote origin
git config branch.master.merge refs/heads/master
Thursday, May 26, 2011
LVM basics
I've just spent a few hours with iSCSI SAN disks (EqualLogic) and Linux Logical Volume Manager (LVM). The abstraction is even deeper than that, because Linux at work is running under VMware, so it is really VMware talking to the SAN and presenting a SCSI disk to Linux. Since I only get into the LVM weeds a couple of times a year, I thought it would be helpful to list the steps I took to get usable disk space under Linux starting with the raw disk space.
Step One - create a new partition
Create a new partition with FDISK or PARTED. Mark the partition type hex 8E for LVM. In my case, the SCSI disk appeared as /dev/sdb and the partition using all space became /dev/sdb1. LVM is capable of using a raw device (no partition type), but I stayed in familiar partitioning territory.
Step Two - create LVM physical volume
pvcreate /dev/sdb1
Step Three - create LVM volume group in the physical volume
vgcreate new_volume_group /dev/sdb1
Step Four - create LVM logical volume in the volume group
lvcreate --name new_logical_volume --size 100G new_volume_group
Step Five - create a file system on the logical volume
mkfs -t ext4 /dev/mapper/new_volume_group-new_logical_volume
Note: Linux device mapper automatically creates a symlink to the disk in /dev/mapper using the volume group and logical volume names. If you choose more meaningful names than the example, the name won't look so awful.
Step Six - turn off automatic file system checks (optional)
tune2fs -c 0 /dev/mapper/new_volume_group-new_logical_volume
Step Seven - add mount point in /etc/fstab
Once the mount point is list in fstab, mount it manually and it is ready to use.
Step One - create a new partition
Create a new partition with FDISK or PARTED. Mark the partition type hex 8E for LVM. In my case, the SCSI disk appeared as /dev/sdb and the partition using all space became /dev/sdb1. LVM is capable of using a raw device (no partition type), but I stayed in familiar partitioning territory.
Step Two - create LVM physical volume
pvcreate /dev/sdb1
Step Three - create LVM volume group in the physical volume
vgcreate new_volume_group /dev/sdb1
Step Four - create LVM logical volume in the volume group
lvcreate --name new_logical_volume --size 100G new_volume_group
Step Five - create a file system on the logical volume
mkfs -t ext4 /dev/mapper/new_volume_group-new_logical_volume
Note: Linux device mapper automatically creates a symlink to the disk in /dev/mapper using the volume group and logical volume names. If you choose more meaningful names than the example, the name won't look so awful.
Step Six - turn off automatic file system checks (optional)
tune2fs -c 0 /dev/mapper/new_volume_group-new_logical_volume
Step Seven - add mount point in /etc/fstab
Once the mount point is list in fstab, mount it manually and it is ready to use.
Wednesday, April 13, 2011
Chrome Revisited
In my first serious test of Mac Chrome back in August, 2010, it came up short compared to other popular web browsers. But Chrome has been evolving fast. And since Firefox 4.0 was just released, it seemed like the right time to run another informal comparison.
What a difference. Chrome has become more stable, faster, and has made huge strides in available and useful plugins. The plugin gap with Firefox was a glaring issue last time. As a web developer, Firefox was indispensable with the Firebug plugin, letting you drill into the CSS and JavaScript acting on individual DOM components. Chrome now has native developer tools that rival Firebug. I am also fond of the Awesome Screenshot plugin that allows you to capture and annotate a web page from within the browser.
While I have found Firefox 4.0 a nice improvement in looks and rendering speed, I have also found it leaks memory, more so on Windows than Linux or Mac. I can rarely make it through a day without the Windows version locking up. That may be an artifact of the slew of plugins I am running and not the Firefox core.
For the last couple of weeks, I have been using Chrome as my primary browser on all platforms and have been very pleased. Competition is a great thing and I am excited to see browsers evolving again after what seemed like a long period of stagnation.
What a difference. Chrome has become more stable, faster, and has made huge strides in available and useful plugins. The plugin gap with Firefox was a glaring issue last time. As a web developer, Firefox was indispensable with the Firebug plugin, letting you drill into the CSS and JavaScript acting on individual DOM components. Chrome now has native developer tools that rival Firebug. I am also fond of the Awesome Screenshot plugin that allows you to capture and annotate a web page from within the browser.
While I have found Firefox 4.0 a nice improvement in looks and rendering speed, I have also found it leaks memory, more so on Windows than Linux or Mac. I can rarely make it through a day without the Windows version locking up. That may be an artifact of the slew of plugins I am running and not the Firefox core.
For the last couple of weeks, I have been using Chrome as my primary browser on all platforms and have been very pleased. Competition is a great thing and I am excited to see browsers evolving again after what seemed like a long period of stagnation.
Sunday, January 23, 2011
Android G2 and iTunes music sync
Getting music from iTunes on a Mac onto an Android G2 smart phone was an easy task. Maybe it wasn't so easy with the first generation Android phones, but the G2 I purchased a couple of weeks ago came with everything I needed.
Connecting the phone to the Mac
My main Mac is a two year old MacBook. The G2 came with a USB sync cable and as soon as I attached it, it opened iPhoto to upload pictures just like a camera. But the G2 also displayed a screen to enable it as a USB disk drive. I enabled disk mode, then took a look at the mounted volume in Finder.
One of the icons on the Volume was DoubleTwist. When I double clicked it, it started downloading the latest Mac version of DoubleTwist. After installation, the DoubleTwist interface looked very much like iTunes. It allows you to automatically sync all music from iTunes or just selections.
Since I don't plan to listen to music often on the G2, I chose to only sync playlists. This only syncs the music required in each playlist. There are a lot of options in DoubleTwist and the integration was seamless.
Connecting the phone to the Mac
My main Mac is a two year old MacBook. The G2 came with a USB sync cable and as soon as I attached it, it opened iPhoto to upload pictures just like a camera. But the G2 also displayed a screen to enable it as a USB disk drive. I enabled disk mode, then took a look at the mounted volume in Finder.
One of the icons on the Volume was DoubleTwist. When I double clicked it, it started downloading the latest Mac version of DoubleTwist. After installation, the DoubleTwist interface looked very much like iTunes. It allows you to automatically sync all music from iTunes or just selections.
Since I don't plan to listen to music often on the G2, I chose to only sync playlists. This only syncs the music required in each playlist. There are a lot of options in DoubleTwist and the integration was seamless.
Sunday, January 2, 2011
Automating FTP
People frequently need to automate FTP sessions to upload or download files.
Most command line FTP clients, including the FTP client on the Mac, can automatically login to an FTP server by reading the .netrc file in the user home directory. Note that the FTP auto-login file starts with a dot in front of the name (dot netrc).
Syntax of the $HOME/.netrc
The .netrc file can contain more than one auto-login configuration. Each FTP server has a set of commands, the minimum being the login name and password. You can create as many machine sections as you need. Here is a generic example:
Very Important: .netrc permissions!
Since user IDs and passwords are stored in the .netrc file, the FTP client enforces permission checking on it. It must be set so that no groups and no other users can read or write to it. You can set the permissions on it with this command from the Terminal (from your home directory) once the file is created:
chmod 700 .netrc
Adding FTP commands in a BASH script
You can embed FTP commands in a BASH script to upload and download files.
For example, you could create a script file named ftpupload.sh:
In this example, I added the -i switch when running FTP to prevent it from prompting on multiple file uploads/downloads, even though it is only uploading one file in the example. I also use the BASH HERE document feature to send commands to FTP. When the script is run, it will auto-login using the information in the .netrc file, change to the right remote directory and upload the datafile.
Scheduling the script with Cron
The last step is to get the BASH script to run unattended, say every day at 5:00 am. The old school UNIX way is to use Cron, but the fancy new Apple way is to use a launchd XML configuration. As long as cron is supported in OS X, I'll stick to the old school way. I leave the launchd configuration as an exercise for the reader.
Add these lines with the command "crontab -e", then save:
Most command line FTP clients, including the FTP client on the Mac, can automatically login to an FTP server by reading the .netrc file in the user home directory. Note that the FTP auto-login file starts with a dot in front of the name (dot netrc).
Syntax of the $HOME/.netrc
The .netrc file can contain more than one auto-login configuration. Each FTP server has a set of commands, the minimum being the login name and password. You can create as many machine sections as you need. Here is a generic example:
machine ftp.server.com
login myuserID
password mypassword
Very Important: .netrc permissions!
Since user IDs and passwords are stored in the .netrc file, the FTP client enforces permission checking on it. It must be set so that no groups and no other users can read or write to it. You can set the permissions on it with this command from the Terminal (from your home directory) once the file is created:
chmod 700 .netrc
Adding FTP commands in a BASH script
You can embed FTP commands in a BASH script to upload and download files.
For example, you could create a script file named ftpupload.sh:
#!/bin/bash
# upload a file
/usr/bin/ftp -i ftp.server.com <<ENDOFCOMMANDS
cd backupdir
cd subdir
put datafile
quit
ENDOFCOMMANDS
In this example, I added the -i switch when running FTP to prevent it from prompting on multiple file uploads/downloads, even though it is only uploading one file in the example. I also use the BASH HERE document feature to send commands to FTP. When the script is run, it will auto-login using the information in the .netrc file, change to the right remote directory and upload the datafile.
Scheduling the script with Cron
The last step is to get the BASH script to run unattended, say every day at 5:00 am. The old school UNIX way is to use Cron, but the fancy new Apple way is to use a launchd XML configuration. As long as cron is supported in OS X, I'll stick to the old school way. I leave the launchd configuration as an exercise for the reader.
Add these lines with the command "crontab -e", then save:
# automated FTP upload
0 5 * * * /Users/username/ftpupload.sh
Wednesday, September 15, 2010
Dumping a Postgresql database remotely with SSH
I ran into a rare problem recently with a large Postgresql database that was filling up the local disks of a server. The database was large, over 100 GB and about 300 million records. There was a lot of churn and it had not been vacuumed in a long time. When I manually ran a vacuum on it, there was not enough working disk space to complete the operation, creating a bind.
What I decided to do instead of using vacuum was to dump it to a remote backup location, then drop the database and restore it from the remote dump. I used SSH to run the remote commands.
Dump a remote Postgresql database to the local machine
ssh user@remote-database-server 'pg_dump database-name -t table-name' > table-name.sql
Restore a remote Postgresql database dump to the local database server
ssh user@backup-machine 'cat table-name.sql' | psql -d database-name
Note that the dump command is run from the backup machine and the restore command is run from the database server.
Also note the single quotes around certain parts of the command.
What I decided to do instead of using vacuum was to dump it to a remote backup location, then drop the database and restore it from the remote dump. I used SSH to run the remote commands.
Dump a remote Postgresql database to the local machine
ssh user@remote-database-server 'pg_dump database-name -t table-name' > table-name.sql
Restore a remote Postgresql database dump to the local database server
ssh user@backup-machine 'cat table-name.sql' | psql -d database-name
Note that the dump command is run from the backup machine and the restore command is run from the database server.
Also note the single quotes around certain parts of the command.
Thursday, August 19, 2010
The Google Chrome experiment
When Google first announced their Chrome browser, packed with a revamped JavaScript engine (V8) and support for offline web apps, I thought I would give it a spin. The first couple of releases were for Windows and Linux -- no Mac version. Those early versions were a little clunky and appeared to offer no better performance than other popular browsers. So I moved on.
When the Mac version became available, it was a much more polished browser. Another theoretical selling point was that each tab ran as a separate process so one crashed tab would not crash the whole browser. I decided to give Chrome a serious work out on my Mac at home.
Things started out well enough and performance was good. I perused the help and learned some of the short cuts. After about three good weeks, something went wrong. I don't know if it was an update, a growing cache, or what, but it started slowing down. Then, it started having problems loading pages from web sites that worked fine in other browsers. It is possible that it even caused wireless network issues, though that is just speculation at the moment. I need to do some more research to see if the problems were related to Chrome.
For now, I am sticking with Firefox as my main browser on the Mac. I'll come back and try Chrome out after the next major release.
When the Mac version became available, it was a much more polished browser. Another theoretical selling point was that each tab ran as a separate process so one crashed tab would not crash the whole browser. I decided to give Chrome a serious work out on my Mac at home.
Things started out well enough and performance was good. I perused the help and learned some of the short cuts. After about three good weeks, something went wrong. I don't know if it was an update, a growing cache, or what, but it started slowing down. Then, it started having problems loading pages from web sites that worked fine in other browsers. It is possible that it even caused wireless network issues, though that is just speculation at the moment. I need to do some more research to see if the problems were related to Chrome.
For now, I am sticking with Firefox as my main browser on the Mac. I'll come back and try Chrome out after the next major release.
Thursday, July 1, 2010
Finding IPs connected to your web server
On Mac OS X
note: this also shows outgoing connections from web browsers
Get all IPs connected to your web server:
netstat -nat | sed -n -e '/ESTABLISHED/p' | awk '{print $5}' | sed 's/\./ /g' | awk '{print $1"."$2"."$3"."$4}' | sort
Get all unique IPs connected to your web server:
netstat -nat | sed -n -e '/ESTABLISHED/p' | awk '{print $5}' | sed 's/\./ /g' | awk '{print $1"."$2"."$3"."$4}' | sort | uniq -c | sort -n
On Linux
Get all IPs connected to your web server:
netstat -ntu | sed -e 's/::ffff://g' | awk '{print $5}' | cut -d : -f1 | sort -n
Get all unique IPs connected to your web server:
netstat -ntu | sed -e 's/::ffff://g' | awk '{print $5}' | cut -d : -f1 | sort | uniq -c | sort -n
Sunday, May 16, 2010
Monday, March 22, 2010
The mysterious Data Center Technical Specialist certification
On March 4, I received an email from Novell Technical Training that I had received a Novell certification for "Data Center Technical Specialist". This came as a surprise to me because I had not applied for this certification, taken any tests for this certification, not had I even heardof this certification.
Due to a cross marketing agreement with the Linux Professional Institute, I had applied for and received the Novell Certified Linux Administrator certification a few weeks prior. This seemed legitimate to me, as I had extensive experience with SUSE Linux and my Linux skills are still sharp. I continue to perform Linux server administration as part of my daily work.
However, I am not quite sure what the Data Center Technical Specialist is supposed to represent. Confused, I wrote to Novell Training asking what the certification meant. I received this equally mysterious reply:
I searched the official Novell Certification web site, and this certification does not appear anywhere. I suspect, but can't confirm that it may be part of the Solution Provider program. As such, it is probably more of a value to Novell sales than to an individual technician. I remain somewhat baffled.
Due to a cross marketing agreement with the Linux Professional Institute, I had applied for and received the Novell Certified Linux Administrator certification a few weeks prior. This seemed legitimate to me, as I had extensive experience with SUSE Linux and my Linux skills are still sharp. I continue to perform Linux server administration as part of my daily work.
However, I am not quite sure what the Data Center Technical Specialist is supposed to represent. Confused, I wrote to Novell Training asking what the certification meant. I received this equally mysterious reply:
Thank you for contacting Novell Training Services. You have received the certification as part of some changes we have made recently to our partner requirements. As part if these changes, some of the exams/certifications you have now count toward the new certification.
I searched the official Novell Certification web site, and this certification does not appear anywhere. I suspect, but can't confirm that it may be part of the Solution Provider program. As such, it is probably more of a value to Novell sales than to an individual technician. I remain somewhat baffled.
Wednesday, March 3, 2010
Fuzzy string matching in PostgreSQL
A recent project required me to use fuzzy string matching, or sound alike matching, in an application that searched a list of names. It turns out there is a contrib module for the PostgreSQL database called fuzzystrmatch that provides several different matching algorithms.
The task at hand involved rewriting a legacy application, originally in PICK, in Ruby on Rails. The PICK application used a soundex search to find names of people that sounded like the search string.
Three algorithms are available as PostgreSQL functions (after installation of the fuzzystrmatch module). They are soundex(), levenshtein(), and metaphone().
Both soundex and metaphone convert a string into character codes. Soundex uses 4 characters and metaphone uses a configurable number of characters. Levenshtein directly compares two strings and returns an integer indicating how well the two strings match.
After some trial and error, I found that metaphone produced better results than soundex. I didn't test the Levenshtein function.
To improve the results, I added a classic substring search using ILIKE. The combination of ILIKE and metaphone gave me a broad, but reasonably accurate fuzzy string search.
The task at hand involved rewriting a legacy application, originally in PICK, in Ruby on Rails. The PICK application used a soundex search to find names of people that sounded like the search string.
Three algorithms are available as PostgreSQL functions (after installation of the fuzzystrmatch module). They are soundex(), levenshtein(), and metaphone().
Both soundex and metaphone convert a string into character codes. Soundex uses 4 characters and metaphone uses a configurable number of characters. Levenshtein directly compares two strings and returns an integer indicating how well the two strings match.
After some trial and error, I found that metaphone produced better results than soundex. I didn't test the Levenshtein function.
To improve the results, I added a classic substring search using ILIKE. The combination of ILIKE and metaphone gave me a broad, but reasonably accurate fuzzy string search.
Friday, February 26, 2010
Linux: fuser to find processes on TCP ports
Note: This is for Linux only. The Mac (BSD) version of fuser does not handle TCP/UDP ports.
Once or twice a year, I run into a problem where a process is using a TCP port and I need to find out which one. I am documenting it here for the next time so I don't have to look it up in man pages.
To see all processes, run fuser as root or with sudo.
To list all processes connected to TCP port 22:
Once or twice a year, I run into a problem where a process is using a TCP port and I need to find out which one. I am documenting it here for the next time so I don't have to look it up in man pages.
To see all processes, run fuser as root or with sudo.
To list all processes connected to TCP port 22:
fuser -n tcp 22Thursday, January 21, 2010
Rails 2.x scaffolding field types
Dude, where's my CRUD?
One of the powerful features of Rails 1.x was the ability to generate CReate, Update, and Delete (CRUD) admin screens automatically using the scaffolding script built into Rails.
The original scaffolding read the database models and created basic, but usable screens to let you add and edit database records. When the 2.x release of Rails came out, scaffolding lost that power. Now, you have to manually specify each table field and type on the command line when running scaffold. If you don't, the generated screens will be empty.
Worse, a basic reference to all valid field types was missing. Here are all the valid types I have been able to dig up:
string
text (long text, up to 64k, often used for text areas)
datetime
date
integer
binary
boolean
float
decimal (for financial data)
time
timestamp
A mapping of the scaffolding types to data types in corresponding databases can be found on Overooped.
Here is an example of using 2.x scaffolding with data types, run from the Rails application root directory:
ruby script/generate scaffold Modelname name:string title:string employed_on:date remarks:text
Here is an example of using rails 3.x scaffolding with data types, run from the Rails application root directory:
ruby script/rails generate scaffold Modelname name:string title:string employed_on:date remarks:text
Thursday, December 24, 2009
You ARE your operating system (among other things)
Whenever you make a choice among products with similar functions, that choice spills over into the realm of social status.
Cars are a common example where social rank often goes with brand, and even within brand, by model, and even within model, by variations, upgrades, and badges. All signify some social status. I became acutely aware of this after purchasing a car that did not fit my image. It was uncomfortable for everyone.
Your operating system
You can see the social aspect tied to an operating system by looking at the Apple "I'm a Mac" campaign, and the weak Microsoft "I'm a PC" campaign response. A choice to run Linux or other operating system also carries connotations and shared group identity. In this sense, you are your operating system.
Your collection of choices
Whether conscious or not, decisions and choices about purchases you make, where choices are available, weave together part of your social tapestry. The schools you attend, where you work, your clothes, your car, where you live, and yes, your operating system. You are those things, at least socially.
The question is, in the context of a consumer society, can a choice be made without the attachment of social status?
Cars are a common example where social rank often goes with brand, and even within brand, by model, and even within model, by variations, upgrades, and badges. All signify some social status. I became acutely aware of this after purchasing a car that did not fit my image. It was uncomfortable for everyone.
Your operating system
You can see the social aspect tied to an operating system by looking at the Apple "I'm a Mac" campaign, and the weak Microsoft "I'm a PC" campaign response. A choice to run Linux or other operating system also carries connotations and shared group identity. In this sense, you are your operating system.
Your collection of choices
Whether conscious or not, decisions and choices about purchases you make, where choices are available, weave together part of your social tapestry. The schools you attend, where you work, your clothes, your car, where you live, and yes, your operating system. You are those things, at least socially.
The question is, in the context of a consumer society, can a choice be made without the attachment of social status?
Saturday, December 5, 2009
Calculating the square root of 2 longhand
There are many numerical methods to calculate square roots. This is the long hand method I learned in junior high. It produces one (accurate) digit at a time, but the working numbers get larger each iteration. Eventually, it bogs down because it is doing math with integers hundreds, then thousands of digits long.
Still, it is fun for tinkering. If you run this Ruby script as is, it will calculate the square root of 2 to 1,000 digits. To adjust the precision, change the number of iterations on this line:
Here is the entire script...
Still, it is fun for tinkering. If you run this Ruby script as is, it will calculate the square root of 2 to 1,000 digits. To adjust the precision, change the number of iterations on this line:
while iterations < 1000Here is the entire script...
#!/usr/bin/ruby
# calculate a square root of 2 using longhand
def newroot(divisor, doubleroot)
# calculate new root
# formula is doubleroot _ * _ = closest to divisor
# try 9, then 8, then 7 ...
i = 9
while i >= 0
multiple1 = (doubleroot.to_s + i.to_s).to_i
multiple2 = i
product = multiple1 * multiple2
if product <= divisor
# found new root
root = i
# get modulus
modulus = divisor - product
break
end
i = i - 1
end
return root, modulus
end
roots = Array.new
# the nearest root to 2 is 1
root = 1
roots.push(root)
remainder = 2 - root
doubleroot = root * 2
divisor = remainder * 100
iterations = 0
while iterations < 1000
root,remainder = newroot(divisor, doubleroot)
roots.push(root)
# compute new doubleroot
return root, modulus
end
roots = Array.new
# the nearest root to 2 is 1
root = 1
roots.push(root)
remainder = 2 - root
doubleroot = root * 2
divisor = remainder * 100
iterations = 0
while iterations < 1000
root,remainder = newroot(divisor, doubleroot)
roots.push(root)
# compute new doubleroot
doubleroot = roots.to_s.to_i * 2
# compute divisor
divisor = remainder * 100
iterations = iterations + 1
print "iteration " + iterations.to_s + "\n"
end
print "final roots are " + roots.to_s + "\n"
Subscribe to:
Posts (Atom)