Thursday, January 31, 2013

Track your time working on PHP projects

Have you ever had a project manager? You know, the kind of person that comes to bug you about your timesheet not being properly done and how important it is? Well, as annoying as they can be, we must thank them and give them credit because it is indeed important. Even if you are a freelancer, you want to know roughly how much time you spent on a project to know if you billed the client correctly.

For years I hated timesheets. I am not particularly thorough at doing them either, so it just gets worse and worse. Fear not, I think I may have found a neat solution. The idea is to track when a PHP file is executed and log which project it belongs to.

To use my script, just follow the instructions in comments, but basically you will add it as a auto_prepend_file in your php.ini and it will check if the current script is watched and to which project it belongs to.

It is using a very basic file structure without even writing content. It is simply creating folder and files so you should not see the overhead. In fact, I tested that it creates an overhead of only about 0.3ms (on a SSD).

It also has a threshold to count as continuous several minutes without activity (more details in comments).

So lets say you have this structure:
  • /var/www/client-A/project-1
  • /var/www/client-A/project-2
  • /var/www/client-B/project-1
Well with this script, configured to watch folder /var/www, any PHP called in it would be tracked and you would end up with something like:
  • 2013-01-30
    • client-A 
      • project-1: Time: 3:30
      • project-2: Time: 1:30
    • client-B
      • project-1: Time: 2:00
  • 2013-01-31
    • client-B
      • project-1: Time: 8:30
Very very useful to build timesheets.


Now, of the people I have showed this, a lot have said that it tracks a too narrow portion of site development. From what I am used to, I have to disagree. Here's a breakdown of events that would be tracked:
  • Looking or configuring the CMS
  • Testing some CSS/JS/HTML/PHP
  • Testing a new plugin
  • An AJAX request that runs on the page
And what would not:
  • Developing a complicated library
  • Documenting
  • Designing
Well, I rarely design, it’s someone else who does it. Developing a complicated library? It is kinda rare, and when I do, it is linked to some project and I will end up testing it at the same time anyway. The real issue is documentation, but I tend to write it as I go. The threshold helps prevent those events won't be noticed, but in the end, the tool is meant to help, not to be an exact representation of your time.

Tuesday, January 15, 2013

Generating a unique node id per hostname in Puppet

To generate a unique integer ID in Puppet, we can use the hostname and convert is to base 10 using a erb inline template.

Friday, January 4, 2013

Fixing permissions using inotify and ACLs

I was working on a shared hosting project and I noticed the permissions were getting a bit complicated.

For each website:
  • Each user must have read/write permission
  • Each user's group must have read/write permission (reseller access)
  • Apache must have read access
  • Would be nice if admins had read/write as well
New files can appear at any time, created by all those users, and it would be nice to keep trace of who created them. This is where ACLs kick in.

For the case above, you need this command:
setfacl -m 'u:www-data:r-X,g:example-group:rwX,g:sudo:rwX,o::---' "/srv/www/"

ACLs quirks

The problem with ACLs is that they are very fragile and a lot of programs don't propagate them, even if you specify default rules. For example, all programs that move instead of creating will honour the ACL of the directory in which the file was created and the destination. Hence, if you untar the whole website in the directory, the default permissions won't be applied.

Running a script

You could run a script that will loop through all your websites and force the permissions through a cron, but this is a slow process (around 2 minutes on my current setup with ~10 websites), there is a delay before it will run (15-30 minutes, depending on how you set it up), and it is very I/O intensive.


inotify is a library that can warn you if some event occurs on a file or in a folder (recursively). It can be very useful for various tasks like syncing files, doing backups, recording edits progress, etc. inotifywait it simply a program that will wait until the event occurs, so you can execute what you want after.

Watching specifically on CREATE and MOVE events, we can fix the permissions of only the files we need.

The event ATTRIB (chown, chmod, setfacl) was intentionally left out not to cause loops, but it could probably be worked around.

Included below is an example of watching two folders and the corresponding init script. Tested on Ubuntu.