Mac OS X: PHP Notice: Use of undefined constant MCRYPT_RIJNDAEL_128

My setup:

  • OS: Mac OS X Yosemite (10.10.1)
  • Using Homebrew
  • PHP: 5.5.14

I’ve installed an empty Laravel installation and got the following error message when navigating to http://localhost/kanban/public/:

Notice: Use of undefined constant MCRYPT_RIJNDAEL_128 – assumed ‘MCRYPT_RIJNDAEL_128’ in /Library/WebServer/Documents/xxx/config/app.php on line 83

Googling for this error message return many tutorials on how to install mcrypt on Mac OS X (whether building it from source or using Homebrew). The problem was that both the mcrypt and the php55-mcrypt packages were properly installed:

$ brew install mcrypt
Warning: mcrypt-2.6.8 already installed
$ brew install php55-mcrypt
Warning: php55-mcrypt-5.5.20 already installed

Mcrypt was also properly loaded by PHP:

$ php -m | grep mcrypt
mcrypt

$ php -i | grep mcrypt
Additional .ini files parsed => /usr/local/etc/php/5.5/conf.d/ext-mcrypt.ini,
Registered Stream Filters => zlib.*, bzip2.*, convert.iconv.*, string.rot13, string.toupper, string.tolower, string.strip_tags, convert.*, consumed, dechunk, mcrypt.*, mdecrypt.*
mcrypt
mcrypt support => enabled
mcrypt_filter support => enabled
mcrypt.algorithms_dir => no value => no value
mcrypt.modes_dir => no value => no value

Looking at the results of phpinfo() in a Web browser, I could notice two things:

  1. No mention of mcrypt being loaded
  2. Scan this dir for additional .ini files: /Library/Server/Web/Config/php

Actually the directory /Library/Server/Web/Config/php didn’t exist (neither did the parent directories). Since the command line php seemed to scan the directory /usr/local/etc/php/5.5/conf.d for additional .ini files, I did the following:

First, I created the directory PHP wanted to scan:

sudo mkdir -p /Library/Server/Web/Config/php

Then, I created a symbolic link from the crypt ini file loaded by my PHP CLI to this directory:

sudo ln -s /usr/local/etc/php/5.5/conf.d/ext-mcrypt.ini /Library/Server/Web/Config/php/ext-mcrypt.ini

Finally, I restarted Apache:

sudo apachectl restart

After that checking the output of phpinfo() in my browser, I could see the following:

mcrypt

mcrypt support enabled
mcrypt_filter support enabled
Version 2.5.8
Api No 20021217
Supported ciphers cast-128 gost rijndael-128 twofish arcfour cast-256 loki97 rijndael-192 saferplus wake blowfish-compat des rijndael-256 serpent xtea blowfish enigma rc2 tripledes
Supported modes cbc cfb ctr ecb ncfb nofb ofb stream

 

Directive Local Value Master Value
mcrypt.algorithms_dir no value no value
mcrypt.modes_dir no value no value

And the Laravel application was working !

SVN: ra_serf was compiled for serf 1.3.4 but loaded an incompatible 1.2.1 library

When trying to check out my latest WordPress plugin on my Mac, I got the following error message:

# svn co http://plugins.svn.wordpress.org/wp-advertize-it wp-advertize-it
svn: E200019: ra_serf was compiled for serf 1.3.4 but loaded an incompatible 1.2.1 library

The reason for this error message is that although there is no separate Serf package in Homebrew anymore and it is included as a private package in SVN and was still on my machine. So I had to remove it:

# brew remove serf
Uninstalling /usr/local/Cellar/serf/1.2.1...

Now of course the library is missing, so SVN still does not work:

# svn co http://plugins.svn.wordpress.org/wp-advertize-it wp-advertize-it
dyld: Library not loaded: /usr/local/lib/libserf-1.0.dylib
  Referenced from: /usr/local/bin/svn
  Reason: image not found
Trace/BPT trap: 5

So you need to uninstall SVN:

# brew uninstall svn
Uninstalling /usr/local/Cellar/subversion/1.8.8...

and reinstall it:

# brew install svn
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/subversion-1.8.8.mavericks.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring subversion-1.8.8.mavericks.bottle.1.tar.gz
==> Caveats
svntools have been installed to:
  /usr/local/opt/subversion/libexec

Bash completion has been installed to:
/usr/local/etc/bash_completion.d
==> Summary

Switching to user root

Why switch to root ?

When in a shell as a non-root user, you have to use sudo to execute a command which requires root privileges e.g.:

sudo chown henribenoit:_www *

That’s the clean way of doing it: use a non-root user and only use sudo when required. But sometimes it just drives me crazy to prefix most commands with a sudo and I’d just rather switch to the root user, do all I need to do and then switch back.

The alternatives

There are a couple of ways to do this:

  • sudo -i
  • sudo su
  • sudo -s
  • sudo bash

All of them will allow you to switch to the root user but give you an environment more or less mixed with the previous user’s environment. Let’s see what each of these commands actually does.

In the sections below, I’ll execute the following command after switching to root with the respective commands:

env | grep "SHELL=
USER=
PATH=
PWD=
HOME=" | grep -v OLDPWD | sort -u

When running it before switching to root, I do get:

HOME=/Users/henribenoit
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/henribenoit
PWD=/Library/WebServer/Documents
SHELL=/bin/bash
TESTPWD=/tmp
USER=henribenoit

Note that I’ve updated the PATH adding the directory /Users/henribenoit to check whether the PATH is being reset and I’ve also added a dummy environment variable TESTPWD to check whether it’s still in there after switching to root. I made these 2 changes executing the following:

export PATH=$PATH:/Users/henribenoit
export TESTPWD=/tmp

sudo -i

Of all four options, sudo -i is the one which will give you the purest environment.

Running the command above, you will get:

HOME=/var/root
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/henribenoit
PWD=/var/root
SHELL=/bin/sh
SUDO_USER=henribenoit
USER=root

So it did take over the PATH I had defined before switching users but changed the home directory, the current directory, the shell used and the current user. Also the additional dummy variable was not taken over.

sudo su

Running the command above after using sudo su, returns the following:

HOME=/var/root
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/henribenoit
PWD=/Users/henribenoit
SHELL=/bin/sh
SUDO_USER=henribenoit
USER=root

Here the PATH and the current directory were not changed after switching to root. The rest was changed and the dummy variable is also not present anymore.

So the difference between sudo -i and sudo su seems to be that sudo -i additionally changes the current directory.

sudo -s

This command takes over even more of the environment before the user switch:

HOME=/Users/henribenoit
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/henribenoit
PWD=/Users/henribenoit
SHELL=/bin/bash
SUDO_USER=henribenoit
USER=root

So the home directory, the path, the current directory and the shell did not change after using sudo -s. So only the current user was changed to root and the dummy variable is not available anymore.

The difference between sudo su and sudo -s is that the latter does not change the shell and home directory.

sudo bash

This one gives you the exact same environment as the previous one:

HOME=/Users/henribenoit
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/henribenoit
PWD=/Users/henribenoit
SHELL=/bin/bash
SUDO_USER=henribenoit
USER=root

Even if you check all variables returned by env, you will see that there is no difference.

Which one to use ?

As always, it depends on what you will do after switching to root.

Changing the home folder will:

  • change the command history you are accessing
  • have an impact on some program installers

I usually do not have an issue with installers referencing the HOME directory. But in some cases I find it useful to keep the history I had with the previous user. In this case, I rather go for sudo -s or sudo bash.

Obviously using a different shell will force you to potentially use a different syntax. That’s why I only use sudo su if I need to the HOME directory to change to root’s home directory.

If you’ve already navigated to the directory you want to work in, the you shouldn’t use sudo -i as it will change the current directory. If it’s the first command you run after opening a shell, the it probably doesn’t really matter.

So in most cases I do use sudo -s (it’s 2 characters shorter than sudo bash ;-)) and in some rare cases sudo su. I personally never use sudo -i (anyway keeping sudo -s and sudo su in mind is already a lot for my small brain and remembering a third option will cause some overflow…).

And remember the additional password check which gets on your nerve when prefixing your commands with sudo once in a while might save you some day (especially if you start cleaning up files early in the morning before even having your first coffee of the day). So only switch to the root user if you really have to. Otherwise execute all commands you can with another user and only the ones which need root privileges with the root user.

Mac: PHP Startup: Unable to load dynamic library gettext

I’ve started today a new project in PHP on my Mac and started with the following error message in my php error log file:

[19-Jan-2014 10:39:14 UTC] PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib/php/extensions/no-debug-non-zts-20100525/php_gettext.dll' – dlopen(/usr/lib/php/extensions/no-debug-non-zts-20100525/php_gettext.dll, 9): image not found in Unknown on line 0

So first you’ll notice it’s looking for a DLL on my Mac so obviously it won’t work. The first thing to check is php.ini:

$ grep extension= /etc/php.ini | grep -v "^;"
extension=php_gettext.dll

Ok so it’s really writte .dll in there. I’m not too sure whether I did it some time ago or whether it was installed like this. I’m pretty sure it used to work fine in the past since I was working on another project which didn’t have any problem with gettext. Inbetween I’ve upgraded to Mavericks but it might just be that I was working very late at night and modified php.ini on my Mac instead of doing it in my Windows virtual machine.

So I changed .dll to .so but without better results. Of course, I had checked the referenced extensions path first, I’d have seen that there are no files there except for xdebug.so.

So it looks like I’ll have to install php_gettext first. That’s not sp difficult.

First you need to find out which version of PHP is installed so that you can download the sources for this version:

$ php --version | head -1 | awk ' { print $2; } '
5.4.17

If you have a different version, you’ll need to change 5.4.17 to that version in all commands below.

Then create a working directory for building gettext for PHP:

mkdir /tmp/gettext
cd /tmp/gettext

Now we need to download the PHP sources and uncompress them:

curl --location --progress-bar http://museum.php.net/php5/php-5.4.17.tar.gz | tar -zx

Then we’ll install the latest version of gettext using Homebrew:

brew update
brew install gettext

Then we’ll prepare the PHP extension for compiling:

$ cd /tmp/gettext/php-5.4.17/ext/gettext/
$ phpize
grep: /usr/include/php/main/php.h: No such file or directory
grep: /usr/include/php/Zend/zend_modules.h: No such file or directory
grep: /usr/include/php/Zend/zend_extensions.h: No such file or directory
Configuring for:
PHP Api Version:        
Zend Module Api No:     
Zend Extension Api No:  

So something is missing. After a long search it seems I needed to install the command line developer tools:

$ xcode-select --install
xcode-select: note: install requested for command line developer tools

$ phpize
Configuring for:
PHP Api Version:         20100412
Zend Module Api No:      20100525
Zend Extension Api No:   220100525

Now it looks better so we can continue, with configuring and building gettext (use the version number installed by brew instead of 0.18.3.2 in the command below):

$ ./configure --with-gettext=/usr/local/Cellar/gettext/0.18.3.2
...
$ make
...
----------------------------------------------------------------------
Libraries have been installed in:
   /tmp/gettext/php-5.4.17/ext/gettext/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 `DYLD_LIBRARY_PATH' environment variable
     during execution

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------

Build complete.
Don't forget to run 'make test'.

So the shared library /tmp/gettext/php-5.4.17/ext/gettext/modules/gettext.so was created and we just need to copy it as php_gettext.so with:

$ sudo cp /tmp/gettext/php-5.4.17/ext/gettext/modules/gettext.so /usr/lib/php/extensions/no-debug-non-zts-20100525/php_gettext.so

And restart apache:

$ sudo /usr/sbin/apachectl restart

And now the error is gone ! You can now safely remove the directory /tmp/gettext.

How to use SVN 1.8 with Eclipse

In this post I’m using Subclipse. I am not too sure whether you’d have the same problem with Subversive or whether it can be fix in the same way. Also I am working on a Mac. Of course the actual solution to this problem is not Mac OS X specific but would also work with Linux. So if you are using Eclipse and Subversion, just ignore the Mac specifics (e.g. Homebrew) and keep reading.

I installed subversion 1.8 using Homebrew some time ago but Eclipse kept using the old svn version so I didn’t have to upgrade my working copies. Now I tried to update a working copy from the command line (it contains documents and not code. That’s why I didn’t do it in Eclipse) and saw that I hadn’t upgraded it yet:

$ svn up
svn: E155036: Please see the 'svn upgrade' command
svn: E155036: The working copy at '/Users/henribenoit/workspace/kanban'
is too old (format 29) to work with client version '1.8.0 (r1490375)' (expects format 31). You need to upgrade the working copy first.

No big deal, I just upgraded all working copies:

$ svn upgrade

Now I could update them:

$ svn up
Updating '.':
At revision 303.

But now I couldn’t synchronize the working copies with the repository using Eclipse any more because eclipse was using the old svn version:

Problems reported while synchronizing SVNStatusSubscriber. 0 of 1 resources were synchronized.
An error occurred synchronizing /kanban: Error getting status for resource P/kanban org.apache.subversion.javahl.ClientException: svn: E155021: This client is too old to work with the working copy at
‘/Users/henribenoit/workspace/kanban’ (format ’31’).
Error getting status for resource P/kanban org.apache.subversion.javahl.ClientException: svn: E155021: This client is too old to work with the working copy at
‘/Users/henribenoit/workspace/kanban’ (format ’31’).
org.apache.subversion.javahl.ClientException: svn: E155021: This client is too old to work with the working copy at
‘/Users/henribenoit/workspace/kanban’ (format ’31’).
org.apache.subversion.javahl.ClientException: svn: E155021: This client is too old to work with the working copy at
‘/Users/henribenoit/workspace/kanban’ (format ’31’).

Actually I had already installed subversion 1.8 but I didn’t install it with the Java language bindings (which I did when I installed svn 1.7). So to get a clean system, I removed svn:

$ brew remove subversion
Uninstalling /usr/local/Cellar/subversion/1.8.0...

And wanted to install it again with the java bindings and as universal binaries (with 32bits and 64bits support), but got an error message:

$ brew install --universal --java subversion
Error: subversion dependency serf not installed with:
--universal

So I had to remove serf so that it can be installed also as a universal binary:

$ brew remove serf
Uninstalling /usr/local/Cellar/serf/1.2.1...

And after serf, came sqlite:

$ brew install --universal --java subversion
Error: subversion dependency sqlite not installed with:
--universal
$ brew remove sqlite
Uninstalling /usr/local/Cellar/sqlite/3.8.0...

Now I could install subversion but it didn’t manage to create all the links because some links were left over from an older installation:

$ brew install --universal --java subversion
==> Installing subversion dependency: sqlite
...
==> Installing subversion dependency: serf
...
==> Installing subversion
...
Warning: Could not link subversion. Unlinking...
Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
You can try again using `brew link subversion'

Possible conflicting files are:
...

It’s easy to fix by using the –overwrite option with brew link:

$ brew link --overwrite subversion
Linking /usr/local/Cellar/subversion/1.8.0... 108 symlinks created

Now svn 1.8 is installed properly (including the Java language binding for the Subversion API i.e. JavaHL). But when I tried in Eclipse to synchronize with an svn repository, I got the following error message:

Incompatible JavaHL library loaded. Subversion 1.7.x required.

This basically means that this version of JavaHL is not supported by the installed version of subclipse. In fact, the Subversion Wiki also gives you this info:

Subclipse Version SVN/JavaHL Version
1.10.x 1.8.x
1.8.x 1.7.x
1.6.x 1.6.x
1.4.x 1.5.x
1.2.x 1.4.x
1.0.x 1.4.x

You can check which version of Subclipse is installed in the “About Eclipse” menu item (click there on “Installation details” and search for Subclipse). If you see e.g. that Subclipse 1.8.1 is installed, the table tells you it will only work with svn 1.7. So we need a newer version of Subclipse. My first idea was to run an update in Eclipse. But it updated some other software but nothing related to subclipse. Then I notice that the update site I had used to install subclipse was: http://subclipse.tigris.org/update_1.8.x

This means that it will provide minor updates like 1.8.2, 1.8.3 and so on but no major update like the version 1.10.x that we need for svn 1.8. So I added a new update site for Subclipse 1.10.x: http://subclipse.tigris.org/update_1.10.x/

Then installed Sublipse 1.10.2 from this update site and after my sync with the svn repository was successful !

Optimize images on Linux and Mac

Most website have many images. You might not be aware of it but it does. I mostly have text and code in my posts and thought I do not need to care too much about optimizing the images in there because there are rarely any. But the fact is that even though my posts mostly do not contain images, the theme I use as well as a few plugins do use images.

If you are using WordPress, you can easily optimize (and compress) images in your post using a plugin. I’ve used WP Smush.it and EWWW Image Optimizer. First I used WP Smuch.it but at some point in time it stopped working so I switched to EWWW Image Optimizer. But when WP Smush.it got fixed I switched back since I felt more confortable with it.

But these plugins only optimize images in the media library. Not images part of themes or plugins. Since most images on my site fall under this category, I had to find a solution. I didn’t find a plugin for this but two nice command line tools.

Why two ? Well because one of them takes care of PNG files and the other one takes care of JPEG files.

First, the PNG files. I optimize them using a command line tool call optipng. You can install it like this under Linux:

apt-get install optipng

(note that you might need to add a sudo before the apt-get)

On Mac, using Homebrew:

brew install optipng

To use the tool, you just need to provide a file to optimize:

optipng myfile.png

If you need to optimize all images in a given folder:

find . -iname "*.png" -exec optipng {} \;

If you want an even better optimization and can leave with a very long optimization duration, add the -o7 Option:

find . -iname "*.png" -exec optipng -o7 {} \;

Now, the JPEG files. For this I used a command line tool called jpegoptim.

Installation under Linux:

apt-get install jpegoptim

On Mac with Hombrew:

brew install jpegoptim

And just provide a file to optimize:

jpegoptim myfile.jpg

For a bulk optimization:

find . -iregex ".*\.jpe?g" -exec jpegoptim {} \;

This performs a lossless optimization (this means the pixels you’ll see are still the same but the file is smaller). Without loss of quality you can still get smaller file but if you can live with a lower image quality, you can achieve a better optimization:

find . -iregex ".*\.jpe?g" -exec jpegoptim --max=75 {} \;

This means you are ready to loose up to 25% quality in order to get smaller files.

Note that you can also optimize images online using Smush.it.

Also remember if you use WordPress that images in plugins and themes will be overwritten by every update of the plugin or theme. So run these two tools once in a while (at least after updating multiple plugins and themes).

Install svn (subversion) on Mac OS X

I wrote an article about a year ago, about svn (Subversion) being missing in Mountain Lion (10.8) and how to install it manually. Since then, I’ve got a new mac and have used myself this post to install it on the new machine. Since then there has also been new versions of subversion but unfortunately all my software are not compatible with it. So I’ve been looking into this topic again and wanted to share.

Another way to install svn on mac is to use a ditribution package from wandisco. They are available here. Do not use the packages on CollabNet which are outdated.
Unzip the .pkg file and double click on it and follow the instructions to have it installed.

I still like it better with Homebrew since it makes it very easy to upgrade the packages and switch between packages.

To find out the version currently active with Homebrew:

brew info subversion

You can check the versions of subversion which are available using:

brew update
brew versions subversion

This will return multiple lines, one per version, each containing a version number and the checkout command e.g.:

1.8.1 git checkout 55577bb Library/Formula/subversion.rb

Choose the version you want to install e.g. here 1.8.1, switch Homebrew’s prefix,checkout the package and install it:

cd `brew --prefix`
git checkout 55577bb Library/Formula/subversion.rb
brew install subversion

Then reset the formula:

git checkout -- Library/Formula/subversion.rb

You can then switch between versions using brew switch (which updates the symlink in /usr/local/bin to the specified formula version in the Homebrew cellar) e.g.:

brew switch subversion 1.7.3

Of course mechanism can be used for any other Homebrew package.

If you get errors in XCode while accessing working copies created with a newer version, you might need to link the newer version into XCode by doing the following:

  • Create a backup directory for the svn binaries currently used by XCode
  • Moving the current binaries to the backup folder
  • Linking the binaries of the new version installed with Homebrew into Xcode (as a replacement for the moved ones)

You can do that by executing the following and replacing 1.7.4 by the actual subversion version you want to use in XCode:

mkdir /Applications/Xcode.app/Contents/Developer/usr/bin/save
mv /Applications/Xcode.app/Contents/Developer/usr/bin/svn* /Applications/Xcode.app/Contents/Developer/usr/bin/save/
ln -s /usr/local/Cellar/subversion/1.7.4/bin/svn* /Applications/Xcode.app/Contents/Developer/usr/bin/

Note that you can also use Homebrew-versions instead. It provides multiple formulas for different versions of existing packages e.g. subversion1.6 and subversion1.7. If you use it, you will of course not be able to upgrade from 1.7 to 1.8 but only from 1.7.2 to 1.7.3 but it’s maybe what you are after…

You can install from Homebrew-versions using:

brew install https://raw.github.com/Homebrew/homebrew-versions/master/subversion17.rb

You’ll notice that Homebrew-versions only has packages for subversion 1.6 and 1.7. But I guess 1.8 should come soon.

So there are quite a few ways to install subversion on your mac and handle different versions. The one I like best is still just installing it with Homebrew and switching to the one I use most. The other versions are still available by other switching to a particular version as shown above or by using the svn command from a particular version in the Homebrew Cellar e.g.

/usr/local/Cellar/subversion/1.7.4/svn

Mac OS X: The operation can’t be completed because the item is in use

Once in a while I can’t empty the trash because one file is in use. It doesn’t happen very often but once in a while. You then get such an error message:

trash file in use

When you then press continue all other files in the trash but this one file are removed. Mac OS X won’t let you delete this file as long as it’s in use. Unfortunately, it won’t tell you which program is using it.

There is an effective brute force method to solve the problem and a more elegant one. First the brute force method: You can delete the files in the trash from a terminal window. The trash is located in a .Trash folder in your user directory. You can get there with:

cd ~/.Trash

You will the file in there. You can just remove everything from the trash using:

rm -rf *

But you have to be careful. This command will delete everything recursively starting from the directory where you are. If you misspelled the directory and are not actually in the trash but in your user directory, it will delete many things you did not intend to delete. A solution for this problem is to combine the two commands above and only execute the second one if the first one was successfull. This is done combining them with &&:

cd ~/.Trash && rm -rf *

Of course deleting a file which is in use by a program might lead this problem to have an unpredictable behavior. So now to the more elegant solution. Instead of just deleting everything from the command line, we’ll first try to figure out which program is actually using the file. This is done using the lsof command:

Lsof lists on its standard output file information about files opened by processes.

It will basically return a list of all files (among other things) are opened by which process. We can then redirect the output to grep to filter by the file name which is in use (in my case some_file.mp4):

$ lsof | grep some_file.mp4
QuickTime 81275 henribenoit    5r     REG                1,2 192918592 32326555 /Users/henribenoit/.Trash/some_file.mp4

So now, you know it’s Quicktime. If the process name displayed in there is not so clear, you can get a full command line for the process which is preventing the file from being deleted. If you want to kill the process you can just use the commands at the end of this post. But I’d actually like to find out about the program and close it properly. This can be done by using the ps command:

$ ps 81275
  PID   TT  STAT      TIME COMMAND
81275   ??  S      0:58.83 /Applications/QuickTime Player.app/Contents/MacOS/QuickTime Player -psn_0_17662167

So we now we have the full command line (in this case it wasn’t required but does help in some cases). You can also combine the commands above into one with the same results:

$ ps `lsof | grep some_file.mp4 | awk ' { print $2; } '`
  PID   TT  STAT      TIME COMMAND
81275   ??  S      0:58.83 /Applications/QuickTime Player.app/Contents/MacOS/QuickTime Player -psn_0_17662167

If you ever get a command name for which you cannot find the corresponding program, you have two options: search for the parent process or just kill the process (note that wild process killing doesn’t really improve the stability of the system).

First we’ll lookup the parent process. This can be done using ps but we need to add the -f option to see the process ID of the parent process:

$ ps -f `lsof | grep some_file.mp4 | awk ' { print $2; } '`
  UID   PID  PPID   C STIME   TTY           TIME CMD
  501 81275   135   0  8:52PM ??         0:58.84 /Applications/QuickTime Player.app/Contents/MacOS/QuickTime Player -psn_0_17662167

The column PPID shows the parent process ID. Now we can use ps once again to get info about the process 135:

$ ps 135
  PID   TT  STAT      TIME COMMAND
  135   ??  Ss     0:16.98 /sbin/launchd

Of course in my case it’s not very interesting since the blocking process is an application so the parent is launchd. But in other cases, it might be useful. You can recurse until you find an applicaiton you acn close. If none of this work, you need to either force the deletion of the files as shown above or you need to kill the process:

$ kill 81275 && ps 81375
  PID   TT  STAT      TIME COMMAND

Now the blocking process is gone and you can fully empty the trash can. If the process doesn’t exit on kill, you should add the -9 option to force kill the process:

$ kill -9 81275 && ps 81375

Mac OS X: List listening ports and programs using netstat

When checking the listening ports on my Linux machine I put netstat some pants on:

# netstat -pant | grep LISTEN
tcp        0      0 0.0.0.0:1024            0.0.0.0:*               LISTEN      20797/sasdwl
tcp        0      0 192.168.230.236:3873    0.0.0.0:*               LISTEN      21201/java
tcp        0      0 0.0.0.0:4999            0.0.0.0:*               LISTEN      28475/pcp
tcp        0      0 192.168.230.236:2055    0.0.0.0:*               LISTEN      20037/dataserver
tcp        0      0 127.0.0.1:8009          0.0.0.0:*               LISTEN      21201/java
tcp        0      0 0.0.0.0:1098            0.0.0.0:*               LISTEN      21201/java
tcp        0      0 0.0.0.0:9002            0.0.0.0:*               LISTEN      20731/sasfrompacs
tcp        0      0 192.168.230.236:2058    0.0.0.0:*               LISTEN      20475/backupserver
tcp        0      0 0.0.0.0:139             0.0.0.0:*               LISTEN      28306/smbd
tcp        0      0 0.0.0.0:1099            0.0.0.0:*               LISTEN      21201/java
tcp        0      0 0.0.0.0:33518           0.0.0.0:*               LISTEN      21201/java
tcp        0      0 0.0.0.0:4847            0.0.0.0:*               LISTEN      21201/java
tcp        0      0 0.0.0.0:33519           0.0.0.0:*               LISTEN      21201/java
tcp        0      0 0.0.0.0:4848            0.0.0.0:*               LISTEN      21201/java
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      19532/httpd
tcp        0      0 0.0.0.0:4849            0.0.0.0:*               LISTEN      21201/java
tcp        0      0 0.0.0.0:33521           0.0.0.0:*               LISTEN      21201/java
tcp        0      0 0.0.0.0:1234            0.0.0.0:*               LISTEN      21201/java
tcp        0      0 0.0.0.0:8083            0.0.0.0:*               LISTEN      21201/java
tcp        0      0 0.0.0.0:5432            0.0.0.0:*               LISTEN      21201/java
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      5342/master
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      19532/httpd
tcp        0      0 0.0.0.0:4444            0.0.0.0:*               LISTEN      21201/java
tcp        0      0 0.0.0.0:445             0.0.0.0:*               LISTEN      28306/smbd
tcp        0      0 0.0.0.0:8093            0.0.0.0:*               LISTEN      21201/java
tcp        0      0 0.0.0.0:4445            0.0.0.0:*               LISTEN      21201/java
tcp        0      0 0.0.0.0:4446            0.0.0.0:*               LISTEN      21201/java
tcp        0      0 127.0.0.1:2054          :::*                    LISTEN      20542/java
tcp        0      0 :::22                   :::*                    LISTEN      5025/sshd
tcp        0      0 ::1:25                  :::*                    LISTEN      5342/master

I want to see the ports and the programs listening on these ports. The netstat options used mean:

  • -p: show the program name / PID owning the socket
  • -a: show all connections
  • -n: show numerical addresses
  • -t: show only TCP connections

Somehow I’ve only noticed now that netstat on Mac OS X cannot show the program name. Actually on Mac OS X, the -p parameter of netstat doesn’t mean program or process but protocol. Also there is no -t parameter but it can be done using -ptcp.

$ netstat -an -ptcp | grep LISTEN
tcp4       0      0  127.0.0.1.10000        *.*                    LISTEN
tcp6       0      0  *.43611                *.*                    LISTEN
tcp4       0      0  *.43611                *.*                    LISTEN
tcp46      0      0  *.80                   *.*                    LISTEN
tcp4       0      0  127.0.0.1.3306         *.*                    LISTEN
tcp4       0      0  127.0.0.1.631          *.*                    LISTEN
tcp6       0      0  ::1.631                *.*                    LISTEN

There seems to be no way to get the same kind of info using netstat on Mac OS X. But everything is not lost. A tcp socket is just another type of file descriptor in Unix derivatives so we can use lsof to get the same info on Mac OS X:

$ lsof -i -P | grep -i "listen"
mysqld    31797 henribenoit   10u  IPv4 0xe1e3f49df503def7      0t0  TCP localhost:3306 (LISTEN)

This shows you the listening ports for programs running under your user name. If you want to see it for all users, you’ll have to use sudo.

$ sudo lsof -i -P | grep -i "listen"
launchd       1           root   28u  IPv6 0xe1e3f49dedc794b7      0t0    TCP localhost:631 (LISTEN)
launchd       1           root   29u  IPv4 0xe1e3f49dedc7f49f      0t0    TCP localhost:631 (LISTEN)
mysqld    31797    henribenoit   10u  IPv4 0xe1e3f49df503def7      0t0    TCP localhost:3306 (LISTEN)

Mac: Failed to build gem native extension

When installing ruby on rails, vagrant, rmagick, sqlite3-ruby, mysql or any other software using ruby native extensions, you might get the following error message:

$ sudo gem install xxxxxx
Password:
Building native extensions.  This could take a while...
ERROR:  Error installing xxxxxx:
	ERROR: Failed to build gem native extension.

I got this error because I was on a new Mac and didn’t have XCode installed on this machine (using another one for Mac development). And since it’s over 1 GB of disk space I’d need for Xcode, I wanted to avoid having to install it just to get this other stuff installed. The alternative are the “command line tools”. So I went to http://developer.apple.com/downloads/, logged in with my Apple ID, downloaded the latest version of the “Command Line Tools (OS X Mountain Lion) for Xcode” and installed them.

But even with the command line tools install, I was still getting the following error message (which was also there before installing the tools):

Configuring libffi for i386
configure: WARNING: if you wanted to set the --build type, don't use --host.
    If a cross compiler is detected then cross compile mode will be used
configure: error: in `/Library/Ruby/Gems/1.8/gems/ffi-1.8.1/ext/ffi_c/libffi-i386':
configure: error: C compiler cannot create executables
See `config.log' for more details
make[1]: *** No targets specified and no makefile found.  Stop.
make: *** ["/Library/Ruby/Gems/1.8/gems/ffi-1.8.1/ext/ffi_c"/libffi-i386/.libs/libffi_convenience.a] Error 2

Then I had a look at config.log, located there (you might have a different path, when using a newer version):

/Library/Ruby/Gems/1.8/gems/ffi-1.8.1/ext/ffi_c/libffi-i386/config.log

And foung the following error:

xcode-select: Error: No Xcode is selected. Use xcode-select -switch , or see the xcode-select manpage (man xcode-select) for further information.

The solution is to use xcode-select but it took me a few tries to find out what I was supposed to use as path without Xcode installed:

sudo xcode-select -switch /usr/lib/

This error was gone but I got a few error messages like this:

xcrun: Error: failed to exec real xcrun. (No such file or directory)

Looking at the man pages:

xcrun provides a means to locate or invoke coexistence- and platform-aware developer tools from the command-line, without requiring users to modify makefiles or otherwise take inconvenient measures to support multiple Xcode tool chains.

Well, it didn’t really help me much…

The command causing looked like this:

xcrun cc -I. -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin12.0 -I. -DRUBY_EXTCONF_H=\"extconf.h\"  -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE   -fno-common -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE  -fno-common  -pipe -fno-common  -I/Library/Frameworks/Mono.framework/Versions/2.10.11/lib/libffi-3.0.11/include    -c MappedType.c

So xcrun just gets a command line as parameters. So first I checked that cc was working:

$ cc --version
Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.4.0
Thread model: posix

Then since just calling cc was working, I was wondering why I’d need xcrun… Maybe the solution is just to create my own xcrun just executing the command line provided as parameters.

First I made a back up of xcrun, then created a shell script there:

sudo mv /usr/bin/xcrun /usr/bin/xcrun.sav
sudo vi /usr/bin/xcrun

Now in vi, I’ve put the following contents in xcrun:

#!/bin/bash
$@

It just execute the same command line but without the first xcrun. Of course, you need to give it execute rights:

sudo chmod +x /usr/bin/xcrun

And then executing gem install finally worked ! I guess there is probably a cleaner way to do it but at least I got it working even though it was late at night and I was almost sleeping on the keyboard !

Update: The trick with xcrun might cause problems installing some other software e.g. osxfuse. So you might have to remove it afterwards:

sudo mv /usr/bin/xcrun /usr/bin/xcrun.sav2
sudo mv /usr/bin/xcrun.sav /usr/bin/xcrun

If you need it again, you can restore it like this:

sudo mv /usr/bin/xcrun /usr/bin/xcrun.sav
sudo mv /usr/bin/xcrun.sav2 /usr/bin/xcrun