Friday, September 28, 2012

Restoring a lost or moved iTunes library

Background

When I installed an SSD in my Macbook Pro, I had to migrate all my files to new locations because the SSD is only 128 GB and my previous HDD was about 500 GB... and it was a little more than half full. So, where do I put them? I used another 500 GB external HDD (Firewire 800) as my Time Machine backup, so now I have 3 drives total. It took about a day, but I finally got everything shuffled around. This included moving my music to the external firewire drive, and thus, also my iTunes library.

The problem

At first, iTunes insisted on keeping the music library stored on my internal drive, in my home folder, in the Music directory. I told it "no, stop that!" several times but it persisted for some reason, refusing to accept my settings of putting the music library on an external drive. Finally, I nuked the silly empty library iTunes made when it started and couldn't find any existing one in my home folder, and closed iTunes.

The solution

iTunes has a couple files in the library folder: iTunes Library.xml and iTunes Music Library.xml. I don't know why there's two, but each one contained about the same things and were 30,000+ lines in length. There's also an important iTunes Library.itl file which is a binary representation of the library, which iTunes uses as its master copy of all your song titles, playlists, metadata, etc. Remove that, and iTunes will create a new empty one in its place. Remove the xml files, and iTunes will simply re-create them upon starting or closing (from the binary file).

I first tried opening iTunes with Option+Click which allows you to choose a new library (folder containing an ITL file) when it starts. This worked fine actually, except that none of the song files could be found: the library had moved to my external drive, but iTunes still expected them in my home folder.

So, I could locate them, one-by-one, or try something else.

The solution... for realz this time

After scouring Google for some time, I was finally led to this article in the Apple knowledge base, which describes how to restore an iTunes library. Summary:

First, since that KB article doesn't cover what to do when your library has moved, I had to figure this out. I opened both of those XML files and did a search-replace for the old paths with the new file paths. It's important to have iTunes closed in this process and not open it up until we're ready.

Then I dragged the ITL file (iTunes Library.itl) to the trash. And I dragged the two XML files to the desktop. Then I started iTunes. It created a new, empty library as expected. I changed the preferences so the library existed on my external hard drive in the folder I wanted. Then I did something very counter-intuitive, according to the KB article. I clicked File -> Library -> Import Playlist. Yeah, sure... except this isn't a playlist. It's a whole library.

However counter-intuitive this may seem, it worked for me. I chose iTunes Library.xml on my desktop and it restored the whole library like a charm. Now, whenever my drive is plugged in, iTunes just works. And when it's not plugged in, iTunes warns me and I can quit without messing anything up.

Wednesday, September 26, 2012

Macbook Pro runs hot with SSD and TRIM Enabler

The first problem


In a recent upgrade to my Macbook Pro (15-inch, early 2011), I swapped out the standard 2.5" HDD for a OCZ Vertex 4 SSD, which has a Sandforce controller Indilinx Everest 2 controller. I also did a clean install of OS X 10.8 (Mountain Lion) on the new drive.

I installed a hard drive performance benchmarking tool (Blackmagic Disk Speed Test) from the App Store and was pleased to see 500 MB+/sec read and write speeds, and my battery life on full charge went up to almost 6 hours! Then I encrypted the volume using FileVault 2 (Mac's built-in encryption utility; works very well). I rebooted, and did another speed test.

Write speeds were down to about 220 MB/sec and read speeds were just over 300 MB/sec. Performance had dropped drastically. Apparently, the FileVault encryption was interfering.

Background


Doing a little research turned up results that Sandforce-controlled SSDs, in Macs, may have trouble performing well when FileVault is doing its pass-thru (or "on-the-fly") encryption. Fortunately, this isn't a Sandforce-controlled drive. So why was this happening?

One possibility: SSDs should have a low-level command called TRIM which improves performance when writing to non-empty blocks on the drive. In a traditional HDD, writing to a non-empty sector has no (measurable) performance hit, but on an SSD, there's some technical reasons that writing to a non-empty block is slower than writing to an emtpy block. TRIM tidies things up after data is "deleted" so that write speeds are quick in that area later. Thus, enabling TRIM manually on Macs, whether there really is trouble or not, should theoretically help boost performance.


TRIM Enabler, the solution .... or is it?

I downloaded the nifty TRIM Enabler program and turned on the TRIM command with an easy switch-flip. After a reboot, I waited about an hour then ran a benchmark test. Performance was back up to 300-350 MB+/sec. Read speeds were even a little higher. I was very pleased. But a few days later, I noticed that my Macbook Pro was running hot and the battery life dropped from about 5.5 or 6 hours to 2 or 2.5, and the fan was spinning hard.

The CPU wasn't running out of control, and I couldn't narrow it down. I suspected it was SSD- or TRIM-related.

The fix to my Macbook Pro running hot / bad battery life

I simply disabled the TRIM command again in TRIM Enabler tool. Now, a day later, my MBP is running at normal temperatures, and battery life is back up to the high marks I was hoping for.

I suspect that the issue wasn't so much with a faulty SSD, but rather that there was some sort of initial lag in performance after encrypting. I don't know why I think it was Spotlight indexing all my files quickly, so the processor had to keep up -- but now a few days later  and without TRIM Enabler on, my benchmark tests show high read and write speeds, again up past the 350+MB/sec mark and my battery life is normal.

tl;dr Just be patient after encrypting your SSD with FileVault. Performance will probably go back up after a day, and the hit isn't too notable unless you're doing specific benchmark testing. TRIM Enabler probably isn't needed (with Vertex 4 SSDs).

Tuesday, September 25, 2012

Printing to BYU campus printers without extra software (Mac OS X)

Macs come with a print server installed by default. This means you don't need to install any drivers or software to print to the BYU campus printers. It's really easy to configure the campus printers natively to print from your Mac.

First open the Terminal, then type: cupsctl WebInterface=Yes and press enter. this enables the "admin panel" we'll use.

Open a browser to: http://127.0.0.1:631/admin. Click Add Printer. You may have to authenticate: type your Mac user name and password (the one you login with when you start it up).

Of all the options that appear, choose "LPD/LPR Host or Printer." Then Continue.

For black & white printers, put: lpd://MYBYUID@isis.byu.edu/CampusBW in the textbox. Or for color, put: lpd://MYBYUID@isis.byu.edu/CampusColor -- Then make sure to replace "MYBYUID" with your myBYU username (formerly "Route-Y" username). Then Continue.

Type a name, description, and location of your choice. I usually call it "CampusBW" (no spaces allowed in the name) -- and the description is similar since that's the text that appears in the list of printers on my Mac. Then Continue.

In the list, choose "Generic" -- then Continue.

In the next list, I usually choose "Generic PostScript Printer (en)" or the option most similar to it, since this varies a little. Then Add Printer.

You're done! When you go to print something, choose the campus printer, then swipe your ID card at any of the Pharos printing stations in buildings around campus.


Source:
https://island.byu.edu/linux/content/how-use-campus-pharos-printing-under-linux (I updated the instructions and added my own notes, as these are a bit dated.)

Installing nginx / PHP / MySQL on Mac OS X Mountain Lion

** Update: See a quicker way to do this using Homebrew (this method uses Macports, and it's considerably more difficult). **







... are you sure you want to use Macports to do this? (See the link above for Homebrew instructions instead!) ...








... okay, fine, continue on if you're sure ....





Introduction

Even though OS X comes with Apache server pre-installed, our production environment at work is nginx. While nginx has downloads for Windows and Linux, there's no official mac port. Fortunately, there's Macports.

Okay, true: Macports isn't required to install nginx on a Mac. It's said that installing nginx without Macports is as easy as wget, ./configure, make, and make install. Unfortunately, I usually run into problems when compiling and installing from source. I'm definitely no Macports junkie, but I am too pressed for time to debug someone else's huge code base to compile on my machine.

That said, here's the lazy way to install a complete web development environment on your Mac. These instructions are designed for a clean install of Mountain Lion (mine is 10.8.2). It's not as bad as it looks, I promise. Except the "prep" section, skip anything you don't want installed. And hey, you'll learn a lot in the process (like I did). It's actually pretty systematic...

Prep

Install Xcode. Sorry, it's gotta happen. Macports needs it. While it's downloading, hop over to Macports.org and get the latest pkg for your system. Or run: wget https://distfiles.macports.org/MacPorts/MacPorts-2.1.2-10.8-MountainLion.pkg from the terminal.

Run Xcode and accept the license agreement. Then go to Preferences --> Downloads and install the "Command Line Tools." It's another 100+ MB to download, but think of this way: you'll be prepared with pretty much every Apple dev tool you'll ever need after today.

Ensure other web servers are off and disabled. This is a great activity while you wait for Xcode to install. On Mountain Lion, you have to use the command line to enable the default Apache server, so never-mind if you've never done that. Lion and prior, it's easily enabled in Sharing preferences ("Web"). Ensure these are off by running ps aux | grep apache or going to http://localhost in your browser.

Install Macports. Just run the .pkg file you downloaded. Make sure you've completed the previous steps first. By default, Macports and all ports will go into /opt/localThe readme file you see at install is super-helpful to know. (By the way, I had a hard time finding that exact readme file anywhere, so I'm hosting my own copy of it on my Raspberry Pi sitting on my windowsill, just for fun.) To be sure, run sudo port selfupdate when it's done installing to be up-to-date.


Install

nginx


Run sudo port install nginx to install nginx. Twiddle thumbs... and at the end of the install, you'll be shown a command that causes it to run at system start: sudo port load nginx.

Configure nginx. Start by setting the default config files:
  • cd /opt/local/etc/nginx
  • sudo cp nginx.conf.default nginx.conf
  • sudo cp mime.types.default mime.types
  • sudo nginx -s reload
  • Load http://localhost in your browser to see that it's working. You're now done installing nginx.

MySQL

Type: sudo port install mysql5-server and twiddle your thumbs again. When it's done, it gives you a command to have it run at start-up if you wish: sudo port load mysql5-server. For some reason, I had to restart my computer to get MySQL to start, but you can do that later. And the default, "root" user password is simply blank which is nice for dev environments.


PHP with FastCGI


Install PHP 5 and FastCGI. The command is long because you have to include all the extensions / helper libraries you want it compiled with. You can pick and choose, but be sure to include some essential ones like mysql, http, etc. I did it in two pieces like this:
  • sudo port install php5 +fastcgi fcgi
  • sudo port install php5-openssl php5-curl php5-gd php5-iconv php5-http php5-mcrypt php5-xdebug php5-mysql
At this point, your development tools and environment should be all there, and now we just need to configure them.

Configure nginx

Edit nginx.conf. In order to develop multiple sites on my Mac, I prefer to use a separate directory in the nginx folder which contains the config files for each domain I'm developing on. I call this "sites-enabled," located in /opt/local/etc/nginx. You can use the default conf file if you want, but you'll want to make sure a line like this appears somewhere before the final curly brace:

include sites-enabled/*;

This pulls in the configuration files from the sites-enabled folder.

Configure nginx site config files. For each domain/site you are developing, create a file inside /opt/local/etc/nginx/sites-enabled (make that directory if you want) called something like "mysite.dev.conf." A basic config file looks like this:

server {
listen 80;
server_name mysite.dev;
root /Users/matt/Sites/whatever/.../path/no-trailing-slash;

location / {
try_files $uri $uri/ /index.html;
}

try_files $uri $uri.html =404;
}

Now don't forget to update your host file: sudo nano /etc/hosts -- this will open your hosts file. Add an entry for each dev domain you use:

127.0.0.1    mysite.dev

Ctrl+O, Enter, Ctrl+X to save and exit. Make sure to reload nginx: sudo nginx -s reload. Now when you type http://mysite.dev in your browser, it will talk to your localhost nginx which should serve up that site based on the domain you are requesting.

If your dev site uses PHP...

...then some special stuff needs to be added to your site config file. To have nginx talk to PHP through FastCGI, my conf file (sites-enabled/mysite.dev.conf) looks kind of like this:

server {
  listen 80;
  server_name mysite.dev;
  root /Users/.../no-trailing-slash/directory;
  index index.php index.html;

  location / {
    #try_files $uri $uri/ /index.php;  # this line was causing the index.php file to be loaded twice...
  } 

  location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(.*)$;
    fastcgi_index index.php;
    include fastcgi.conf;
    if (-f $request_filename) {
       fastcgi_pass 127.0.0.1:9000;
    }
  }

  try_files $uri $uri.php $uri.html =404;
}

Again, don't forget to reload nginx when you make changes.

Last thing: we need to tell nginx where to find translation information for FastCGI, so it knows how to talk to it. Run this command: sudo cp /opt/local/etc/nginx/fastcgi.conf.default /opt/local/etc/nginx/fastcgi.conf

Don't forget to reload nginx!

Run php-cgi (FastCGI) when the Mac boots

Almost done! PHP's CGI needs a little help in order to run when the Mac boots up. This gave me a headache for hours after banging my head against the desk. It's actually simple using launchctl with a plist file all ready for you:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>org.macports.php-cgi</string>
  <key>ProgramArguments</key>
  <array>
    <string>/opt/local/bin/php-cgi</string>
    <string>-b127.0.0.1:9000</string>
    <string>-q</string>
  </array>
  <key>EnvironmentVariables</key>
  <dict>
    <key>PHP_FCGI_CHILDREN</key>
    <string>2</string>
    <key>PHP_FCGI_MAX_REQUESTS</key>
    <string>256</string>
  </dict>
  <key>RunAtLoad</key><true/>
  <key>Debug</key><false/>
  <key>KeepAlive</key><true/>
</dict>
</plist>

I put this in a file: /Library/LaunchDaemons/org.macports.php-cgi.plist. Important: No spaces allowed between "-b" and "127.0.0.1:9000." I don't know why. But that's just how it is. You're welcome to customize anything else if you want.

To finish, then, run: sudo launchctl load org.macports.php-cgi.plist

Now the FastCGI wrapper for PHP will load when your system does, along with MySQL and nginx.

Restart your system and try loading your PHP dev website in your browser! (e.g. http://mysite.dev) -- everything should be working. If not, check your system console to see if FastCGI is failing to start and re-spawning every 10 seconds. That means you have a problem in your plist file.

If MySQL can't connect via PHP and you get a funny error on mysqli_connect kinds of functions, try switching the host from "localhost" to "127.0.0.1" in your connection parameters in your PHP script. This might be related to the plist file we created or something in hosts, maybe even the default MySQL config. I'm not sure, but switching that fixed it for me.

Have fun on your shiny new dev environment!

Fix the Home and End keys on Mac OS X

If you use a keyboard that's not designed specifically for Macs, you probably are familiar with the annoying mapping of the Home and End keys: they scroll to the beginning or end of an entire document, with no regard to the cursor's location.

Fortunately it's an easy fix. (Note: This works for native Cocoa apps only, not X11 programs.)

To get your Home and End keys working properly on Mac OS X (Tiger and up, including Mavericks), simply open the Terminal and do this:

$ cd ~/Library
$ mkdir KeyBindings
$ cd KeyBindings
$ nano DefaultKeyBinding.dict

Put these lines in that file, including the curly braces:

{
/* Remap Home / End keys to be correct */
"\UF729" = "moveToBeginningOfLine:"; /* Home */
"\UF72B" = "moveToEndOfLine:"; /* End */
"$\UF729" = "moveToBeginningOfLineAndModifySelection:"; /* Shift + Home */
"$\UF72B" = "moveToEndOfLineAndModifySelection:"; /* Shift + End */
"^\UF729" = "moveToBeginningOfDocument:"; /* Ctrl + Home */
"^\UF72B" = "moveToEndOfDocument:"; /* Ctrl + End */
"$^\UF729" = "moveToBeginningOfDocumentAndModifySelection:"; /* Shift + Ctrl + Home */
"$^\UF72B" = "moveToEndOfDocumentAndModifySelection:"; /* Shift + Ctrl + End */
}

Press Ctrl+O and then Enter to save the file, and Ctrl+X to exit. Restart your computer to have it take full effect.

Sources:
http://evansweb.info/2005/03/24/mac-os-x-and-home-end-keys
http://soodev.wordpress.com/2011/07/04/mac-os-x-remapping-home-and-end-keys/

Thursday, September 20, 2012

Pre-installed development tools in Mac OS X Mountain Lion

I'm convinced that Macs are great for development of all varieties.

Open your terminal for hours of fun, right out of the box.

I don't think any of these are unique to Mountain Lion (10.8), but in my transition from Windows to Mac about a year ago, I was delighted to discover these things came pre-loaded:

  • Python 2

    $ python
  • PHP 5

    $ php -v
  • Ruby 1.8.7

    $ ruby
  • SQLite3

    $ sqlite3
  • CUPS (print server; useful for printing to university/corporate print networks)

    $ cupsctl


  • OpenSSL

    $ openssl
  • Subversion (I wish it came with git though!)

    $ svn

  • libxml

    $ xmllint
    $ xsltproc
  • Apache server 2.2.22

    $ sudo apachectl start    # start the server

    $ sudo apachectl graceful # restarts gracefully
    $ sudo apachectl stop     # stop the server
  • Java (JRE 6; running these the first time will prompt to install; very easy)

    $ java   # run a Java program
    $ javac  # compile a Java program

And since they're essentially Unix-based, Macs have the usual dd, ssh, scp, sed, grep, nano, vi/vim commands.