Serving django media files from the same host as the passenger app server

WARNING: Please read before continuing ▼

Difficulty: Easy
Time: ~5 Minutes
Last Updated: 20rd September 2010
Applies to: *NIX

The recommended configuration for django is to have any static files, such as script, CSS or images uploaded onto a CDN network. While this is the best configuration for a large site, for toy applications it is overkill.

Also, you may wish to run your development environment using passenger, rather than using manage.py runserver.

To start, we need to make a media directory in your passenger app root, and then create a symbolic link to the admin media files located on your system.

1
2
3
cd /var/www
mkdir media #the directory where our media files will be stored
ln -s /usr/lib/pymodules/python2.6/django/contrib/admin/media/ admin_media

Next, we need to disable passenger on the directories/symlinks we have created, as per the previous article on the blog.

Once this is done, edit settings.py in your django app, specifying the new addresses for your media.

Finally, restart apache, and you should now be able to access the media files you need.

, , , , , ,

No Comments

Serving non-python files from a subdirectory of the passenger root.

WARNING: Please read before continuing ▼

Difficulty: Easy
Time: ~5 Minutes
Last Updated: 23rd September 2010
Applies to: *NIX

Serving non-python or ruby files from a subdirectory below the passenger app root requires a simple change to the site configuration.

Open it up, and add something similar to this under the VirtualHost entry (this example shows the subdirectory phpPgAdmin being disabled, so that phpPgAdmin can be served by php instead):

1
2
3
4
        Alias /phpPgAdmin /var/www/phpPgAdmin
        <Location /phpPgAdmin>
                PassengerEnabled off
        </Location>

Once this is done, restart php and any requests made to yourdomain.com/phpPgAdmin will not be served by passenger.

, , , , , , , , , ,

1 Comment

Serving django apps using Phusion Passenger (mod_rails)

WARNING: Please read before continuing ▼

Difficulty: Moderate
Time: varies
Last Updated: 23rd September 2010
Applies to: *NIX

Phusion passenger is a fast and robust solution for serving python web apps, particularly those using the Django framework.

To start, it is assumed you have a suitably configured *NIX base system. This has been tried using Gentoo and Ubuntu.

The next thing to do is to install apache2. NGINX is also supported, however we will be using apache. It should also be possible to use lighttpd, however, there is no official support for such a configuration.

Passenger prefers to use the worker mpm, however if you wish to run PHP apps on the same server instance, you need to use the prefork mpm.

Next, ensure that you install the django framework (your distribution probably has it available as a package, try “apt-get install python-django” or “zypper in python-django“). Also required is

The next step is to configure a VHost (or the default host if you will only be using a single app) and ensure that it can successfully serve static html files without issue.

Next, you need to add a line to the site config file, “PassengerAppRoot“. This tells passenger where to look for the python application you want to serve on that domain.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<VirtualHost python.app.domain.net:80>
        ServerAdmin adam@omega.org.uk

        PassengerAppRoot /var/www
        DocumentRoot /var/www

        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>

        <Directory /var/www/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>

        ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
        <Directory "/usr/lib/cgi-bin">
                AllowOverride None
                Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny
                Allow from all
        </Directory>

        ErrorLog /var/log/apache2/error.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn

        CustomLog /var/log/apache2/access.log combined
</VirtualHost>

Once this is done, deploy your django app into /var/www, or wherever you specified the passenger app root to be. If you are writing an app from scratch, then the command is “django-admin startproject <projectname>“.

Finally, there is one more step you need to do before passenger will serve your app.

You need to create a passenger_wsgi.py file in the passenger root folder. This file looks like this:

1
2
3
4
5
6
7
8
import os, sys

sys.path.append(os.path.dirname(__file__))
os.environ['DJANGO_SETTINGS_MODULE'] = '<projname>.settings'

import django.core.handlers.wsgi

application = django.core.handlers.wsgi.WSGIHandler()

Once this is done, passenger should now start serving your apps.

One final note is that passenger does not cope very well with fatal errors. There tend to not be written to the browser or logs, making them hard to pin down.

To get around this, you can install python-paste (try “apt-get install python-paste“), and use this to catch any fatal errors.

To enable this, you need to make a small change to passenger_wsgi.py:

1
2
3
4
5
6
7
8
9
import os, sys

sys.path.append(os.path.dirname(__file__))
os.environ['DJANGO_SETTINGS_MODULE'] = '<projname>.settings'

import django.core.handlers.wsgi
from paste.exceptions.errormiddleware import ErrorMiddleware

application = ErrorMiddleware(django.core.handlers.wsgi.WSGIHandler(), debug=True)

If a fatal exception now occurs, it will have a stack trace recorded and emitted to the client. This is useful for testing, but should be used with care in a production environment, as it may expose information such as passwords if not configured correctly.

, , , , , , ,

No Comments

Installing the ssh2 PHP extension, with PHP 5.3

WARNING: Please read before continuing ▼

Difficulty: Moderate
Time: ~5 Minutes
Last Updated: 21st March 2010
Applies to: *NIX

Currently, due to an API change ssh2 will not install via pecl. Despite being a one-line fix, and 5.3 being out for some months now, the maintainers have neglected to make their extension compatible with PHP 5.3

If you recieve an error similar to:

1
2
/tmp/pear/download/ssh2-0.11.0/ssh2.c:52: error: duplicate "static"
/tmp/pear/download/ssh2-0.11.0/ssh2.c: In function "zif_ssh2_methods_negotiated":

Then you are affected. To fix this, you need to download and extract the ssh2 package:

1
2
pecl download channel://pecl.php.net/ssh2-<version>
tar xvf ssh-<version>.tar

Open up ssh2-<version>/ssh2.c and look for the following block around line 50:

1
2
3
4
5
6
7
8
#ifdef ZEND_ENGINE_2
static
    ZEND_BEGIN_ARG_INFO(php_ssh2_first_arg_force_ref, 0)
        ZEND_ARG_PASS_INFO(1)
    ZEND_END_ARG_INFO()
#else
static unsigned char php_ssh2_first_arg_force_ref[] = { 1, BYREF_FORCE };
#endif

From that block, you need to remove the first “static” so it looks like this:

1
2
3
4
5
6
7
#ifdef ZEND_ENGINE_2
    ZEND_BEGIN_ARG_INFO(php_ssh2_first_arg_force_ref, 0)
        ZEND_ARG_PASS_INFO(1)
    ZEND_END_ARG_INFO()
#else
static unsigned char php_ssh2_first_arg_force_ref[] = { 1, BYREF_FORCE };
#endif

After you’ve done this, simply repackage and install:

1
2
pecl package package.xml
pecl install -f ssh2-<version>.tgz

, , , , , , , , ,

No Comments

Software Engineering: Munificent’s ghetto guide to Big-O notation:

The basic idea is that you want a simple formula that converts the number of items you have to process to how long you can expect that to take. So, if you have 20 items and your Big-O is O(n^2), then it’ll take about 400 (of some unspecified unit of time/work) to process.

The actual number doesn’t matter, what matters is how quickly it grows as the number of items grows. Growing slower is better, of course. Because the actual number doesn’t matter, constants are discarded, and lower powers are discarded. O(2n^4 + 3n + 5) is just O(n^4).

Here’s how to roughly estimate the Big-O for your code:

Fixed work
Any random chunk of code that does something once (like, say, printing something to the screen, or initializing a variable) is O(1).

Binary search
If you hunt through the items using a binary search, where at each step you cut your search space in half, that’s O(log n). (That log there is base 2, not 10.) So, finding a number in a sorted array is O(log n). Most algorithms involving binary trees will have a “log” in their Big-O.

Loops
If you loop through all of the items, that’s O(n). So, finding the biggest value in an array of numbers (naïvely) is O(n).

Permutations
If you’re going through every permutation of your items, that’s O(n!). For example, if you’re doing a naïve algorithm to find anagrams using a given set of letters by trying every possible combination, you’re permutating.

Exponentials
The last common Big-O type is O(2^n). The only simple example I can think of is if you need to create a filled binary tree of depth n, then that’ll have O(2^n). There are some other algorithms that have this, but, thankfully, you shouldn’t run into it much.

So those are the basic types in order from best (fastest) to worst. Once you hit O(n!) or O(2^n), you’re in the range of algorithms where your code will very likely be too damn slow. This is why it’s good to know the Big-O of your code.

The question now is, how are these individual parts combined in a big chunk of code?

Sequential
If your code does one thing and then another, then the Big-O of those two parts are added. So, if you do some fixed work and then loop through your items, it’s O(1 + n). Since we discard any lower terms, what this really means is if you do one thing then another, take the bigger Big-O of the two (O(n) in our example).

Nesting
If your code does one thing inside another, then the Big-O of those two parts are multiplied. So, if you loop through all of the items and the loop through them again inside that loop, that’s O(n * n) or just O(n^2). This is the one you’ll need to pay attention to. If your code is calling some function within a loop that also loops through the items, you can end up with worse complexity than you realize.

Another example: if you iterate through each item in the list, and for each item, you do a binary search, that’s O(n * log n), or just O(n log n). Most sorting algorithms are around here. It’s better than O(n^2), but worse than O(n).

Recursion
This is a tricky one. If your code calls itself, it may be the same as nesting, or it could be better, or much worse. It all depends on your exit condition and how the input set is reduced at each recursive step. A recursive binary search only gives you O(log n) because each recursive call cuts n in half. If the recursion reduces the input size by only one each time, you’ve got O(n!).

A computer scientist would probably say this isn’t rigorous at all, but this should be good enough for an engineer. The goal here is to be able to quickly scan your code and get an idea of if it’s going to blow up and take forever or not.

Source: http://www.reddit.com/r/programming/comments/a940e/how_i_hire_programmers/c0gfm6g

, ,

No Comments

Opening an elevated command prompt

WARNING: Please read before continuing ▼

Difficulty: Easy
Time: varies
Last Updated: 29th November 2009
Applies to: OS X, Windows, *NIX

Often when performing system administration, you will come across a command that needs to be run as a more priviliged user. Depending on what operating system you use, the procedure for opening an elevated command prompt varies. Read the rest of this entry »

, , , , , , , ,

No Comments

Comparing the contents of 2 directories

WARNING: Please read before continuing ▼

Difficulty: Easy
Time: Varies
Last Updated: 9th November 2009
Applies to: OS X, and Linux

Sometimes, you can end up with multiple copies of a directory from different times. If the number of files is small, then comparing the contents is easy. With large directories, telling the difference between them can be nearly impossible.

Read the rest of this entry »

, , , ,

No Comments

Resetting Windows product activation notices

WARNING: Please read before continuing ▼

Difficulty: Easy
Time: ~1 Minute
Last Updated: 5th November 2009
Applies to: Windows

Since Windows XP, Microsoft has required that all CD keys are validated with them at install time, to combat piracy. Whilst this generally has little impact, if you have misplaced your CD key, or are waiting for one to arrive, you can end up locked out of your own computer.
Read the rest of this entry »

, , , ,

No Comments

Clearing cached DNS entries

WARNING: Please read before continuing ▼

Difficulty: Expert
Time: ~1 Minute
Last Updated: 1st November 2009
Applies to: Windows, OS X, and Linux

Sometimes, when messing around with domain names (the DNS system), you’ll mis-type an address, and be unable to access your site for a significant length of time. Assuming that the incorrect entry has not been cached on another DNS server somewhere between you and your host, you can clear the list of cached addresses on your own machine to resolve the problem.

Read the rest of this entry »

, , , , , , ,

No Comments

Utilities: Filename Randomiser

Program Information:

This is a small program to change the filenames of all files in the target folder to something random and uniform. This may be useful for, as an example, a number of photos in a directory that are displayed in filename order.

It should go without saying that if you run this on a directory it will rename everything in that directory, so take care.

Read the rest of this entry »

, , , ,

No Comments

Technical Procedures is Digg proof thanks to caching by WP Super Cache