Chapter 15. Debugging CGI Applications
So far, we've discussed numerous CGI applications, ranging from the trivial to the very complex, but we haven't touched upon the techniques needed to debug them if something goes wrong. Debugging a CGI application is not much different than debugging any other type of application, because, after all, code is code. However, since a CGI application is run by a remote user across the network in a special environment created by the web server, it is sometimes difficult to pinpoint the problems.
This chapter is all about debugging CGI applications. First, we'll examine some of the common errors that developers generally come across when implementing CGI applications. These include incorrect server configuration, permission problems, and violations of the HTTP protocol. Then, we'll explore a few tips, tricks, and tools that will help us track down problems and develop better applications.
15.1. Common Errors
This section can serve as a checklist that you can use to diagnose common problems. Here is a list of common sources of errors:
Let's look at each of these in more detail.
15.1.1. Application Permissions
Typically, web servers are configured to run as nobody or another user with minimal access privileges. This is a great preventative step, and one that can possibly salvage your data in the case of an attack. Since the web server process does not have privileges to write to, read from, or execute files in directories that don't have "world" access, most of your data will stay intact.
However, this also create a few problems for us. First and foremost, we need to set the world execute bit on the CGI applications, so the server can execute them. Here's how you can check the permissions of your applications:
$ ls -l /usr/local/apache/cgi-bin/clock -rwx------ 1 shishir 3624 Oct 17 17:59 clock
The first field lists the permissions for the file. This field is divided into three parts: the privileges for the owner, the group, and the world (from left to right), with the first letter indicating the type of the file: either a regular file, or a directory. In this example, the owner has sole permission to read, write, and execute the program.
If you want the server to be able to execute this application, you have to issue the following command:
$ chmod 711 clock -rwx--x--x 1 shishir 3624 Oct 17 17:59 clock*
The chmod command (change mode) modifies the permissions for the file. The octal code of 711 indicates read (octal 4), write (octal 2), and execute (octal 1) permissions for the owner, and execute permissions for everyone else.
That's not the end of our permission woes. We could run into other problems dealing with file permissions, most notably, the inability to create or update files. We will discuss this in Section 15.2, "Perl Coding Techniques" later in this chapter.
Despite configuring the server to recognize CGI applications and setting the execute permissions, our applications can still fail to execute, as you'll see next.
15.1.2. The Pound-Bang
If a CGI application is written in Perl, Python, Tcl, or another interpreted scripting language, then it must have a line at the very top that begins with a pound-bang, or #!, like this:
We've seen this above every script throughout this book. When the web server recognizes a request for a CGI application, it calls the exec system function to execute the application. If the application is a compiled executable, the operating system will go ahead and execute it. However, if our application is a script of some sort, then the operating system will look at the first line to see what interpreter to use.
If your scripts are missing the pound-bang line, or if the path you specify is invalid, then you will get an error. On some systems, for example, perl is found at /usr/bin/perl, while on others it is found at /usr/local/bin/perl. On Unix systems, you can use either of the following commands to locate perl (depending on your shell):
$ which perl $ whence perl
If neither of these commands work, then look for perl5 instead of perl. If you still cannot locate perl, then try either of the following commands. They return anything on your filesystem named perl, so they could return multiple results, and the find command will search your entire filesystem, so depending on the size of the filesystem, this could take a while:
$ locate perl $ find / -name perl -type f -print 2>/dev/null
Another thing to keep in mind: if you have multiple interpreters (i.e., different versions) for the same language, make sure that your scripts reference the one you intend, or else you may see some mysterious effects. For example, on some systems, perl4 is still installed in addition to perl5. Test the path you use with the -v flag to get its version.
15.1.3. Line Endings
If you are working with a CGI script that downloaded from another site or edited with a different platform, then it is possible that the line endings do not match those of the current system. For example, perl on Unix will complain with multiple syntax errors if you attempt to run a file that is formatted for Windows. You can clean these files up with perl from the command line:
$ perl -pi -e 's/\r\n/\n/' calendar.cgi
15.1.4. "Malformed" Header
As we first discussed in Chapter 2, "The Hypertext Transport Protocol ", and Chapter 3, "The Common Gateway Interface", and have seen in all the examples since, all CGI applications must return a valid HTTP content-type header, followed by a newline, before the actual content, like this:
Content-type: text/html (other headers) (content)
If you fail to follow this format, then a typical 500 Server Error will ensue. The partial solution is to return all necessary HTML headers, including content type, as early on in the CGI application as possible. We will look at a very useful technique in the next section that will help us with this task.
However, there are other reasons why we may see such an error. If your CGI application generates errors that are printed to STDERR, these error messages may be returned to the web server before all of the header information. Because Perl buffers output to STDOUT, errors that occur after you have printed the headers may even cause this problem.
What's the moral? Make sure you check your application from the command line before you try to execute it from the Web. If you're using Perl to develop CGI applications, then you can use the -wcT switch to check for syntax errors:
$ perl -wcT clock.cgi syntax error in file clock.cgi at line 9, at EOF clock.cgi had compilation errors.
If there are warnings, but no errors, you may see the following:
$ perl -wcT clock.cgi Name "main::opt_g" used only once: possible typo at clock.cgi line 5. Name "main::opt_u" used only once: possible typo at clock.cgi line 6. Name "main::opt_f" used only once: possible typo at clock.cgi line 7. clock.cgi syntax OK
Pay attention to the warnings, as well. Perl's syntax checker has really improved over the years, and will alert you of many possible errors, such as using non existent variables, uninitialized variables, or file handles.
And finally, if there are no warnings or errors, you will see:
$ perl -wcT clock.cgi clock.cgi syntax OK
To reiterate, make sure your application works from the command line before you even attempt to debug its functionality from the Web.
Copyright © 2001 O'Reilly & Associates. All rights reserved.