Every once in a while I do something really, really stupid. Like, say, for instance, delete a whole directory of very important code that I’m working on and my last backup is a couple of weeks old (because of a server move and my failure to re-setup my cron backup). How did this happen? Well, for one, I was coding at about 5:30 a.m. before my caffeine had set in, and, secondly, I was rm -rf’ing with tab-completion. Almost instantly after I pressed Enter I realized what I had done. Tragedy. Or so I thought…

In Linux, you can undelete files if you are using the ext2 file system. A very handy tool called debugfs allows you to list files marked as deleted. I’m using the ext3 file system (ext2’s successor), so I thought the debugfs solution would work. Unfortunately, ext3 actually zeros out the block pointer (the pointer to the file’s data), so reconstructing the file becomes impossible with debugfs.

So, what to do? I had seen some mailing list posts refering to ‘grepping’ the data from the disk drive. Most everything I lost was code (specifically, Ruby). I attempted to use grep to search my hard disk device (/dev/sda7 in my case), but grep kept erroring out with “memory exhausted” errors. Hrrm.

A rethink of the problem led me to the ’strings’ program, which extracts text from files, stdin, or even a disk device. I dumped all text from the disk partition to a text file like so:


#strings /dev/sda7 > /path/to/big_text_file

Note: It is probably a good idea to put the big text file on a separate partition. Otherwise, you risk writing over some of your deleted files on the partition you are attempting to recover from.

I was now able to open the big_text_file in vim and recover all of my deleted code by searching for particular code snippets. It’s not ideal, but I was able to recover everything. Instead of losing several days worth of work, I only lost a couple of hours.

And, of course, my backup is re-setup.

19 comments

Ruby Code & Style

Well, it’s been almost a month now since the baby came. We’re doing well, but very tired. Adding to my things-to-read-when-I’m-not-so-tired list:

Ruby Code & Style – a new online magazine from Artima about the Ruby language.

0 comments

PL/Ruby and PL/PHP in PostgreSQL

The ability to write procedural language (PL) in Ruby and PHP for PostgreSQL is awesome. I wish Oracle had something similar (and no, I’m not talking about Java).

0 comments

A couple of weeks ago I was installing a development environment at work on CentOS with Apache 2, PHP, and the oci8 module. All configured, make’d, and installed, I was up and running with Apache, PHP, and the Oracle Client tools (sqlplus, etc.) in short order. Everything worked except the oci8 php library functions–they couldn’t find my Oracle instances to connect.

I had covered all of the bases:

  • I could connect with sqlplus to my instance, so the Oracle client worked
  • I had set the ORACLE_HOME with SetEnv in Apache’s configuration file and in bash’s system profile
  • phpinfo() showed the oci8 module as installed and the ORACLE_HOME environment variable as set

This problem had me stumped a good part of an afternoon until I attempted to start Apache directly with apachectl instead of through the ’service’ command used in CentOS. Suddenly, it worked!

A quick shuffle through the service script and I found that it was restricting the environment before calling the service like so:

env -i LANG=$LANG PATH=$PATH TERM=$TERM "${SERVICEDIR}/${SERVICE}"

Hmm. So, only LANG, PATH, and TERM are passed into any service environment: ORACLE_HOME is left out in the cold. And, even though I set it in the httpd.conf file, this is apparently too late for it to make a difference in the php oci8 module. A quick fix in the service script adds the requisite ORACLE_HOME:

env -i ORACLE_HOME=$ORACLE_HOME LANG=$LANG PATH=$PATH TERM=$TERM "${SERVICEDIR}/${SERVICE}"

The line above occurs a few times, so add to each occurance. Voila! It works.

I’m content with this solution for now, but I don’t particularly like having to change the service script, so is there any other way to do this?

Update:This is apparently a common issue: Debian mailing list comment, Gentoo bug, which is fixed with a white list of environment variables in a separate file. I couldn’t find a similar RedHat/CentOS bug. And, the SetEnv in the httpd.conf file is only effective for CGI PHP, which does not work for me because I’m using mod_php

0 comments

back to the future in PHP

We’re using PHP version 4.x in production at work, and I often find myself needing a function that has been implemented in PHP 5. A good example is the array_walk_recursive() function. I needed this in my framework library to recursively walk through an input array with a callback function to strip values of potentially harmful input. The recursive ability was key because the input array could be arbitrarily large, containing several nested arrays.

Now, I could have implemented my own function to do just this, but when we do move to PHP 5 in production, I’d want to recode to use the standard library function. To the rescue comes the PHP_Compat PEAR package, full of functions and constants to help bridge the gap between different PHP versions.

Thanks to Aidan Lister (the lead developer) and others who contributed to this package. It has saved me much coding, and I’m grateful!

0 comments