Getting started with Perl CGI scripting |
Steps to creating a successful Perl CGI script |
We'll use the answers to these questions in the steps below.
2. Write your script with a text editor. Many Windows text editors put carriage returns at the ends of lines which can cause Perl scripts to fail. Any of these will solve that problem:
3. Your first script. Type this in (or copy & paste it) into a new file: #!/usr/bin/perl -w print "Content-type: text/html\n\n"; print "Hello, world"; 4. Save your file with a .cgi extension (e.g., "hello.cgi"). Some webhosts might require a .pl extension, check with them to find out. With Dreamhost you can use either .cgi or .pl. 5. Upload your file. Check with your webhost to see if you have to put it in a special place. Some hosts require that it go in the cgi-bin directory. If your host is Dreamhost you can put it anywhere. 6. Use ASCII mode for the upload. If you upload in binary mode it won't work. 7. Set permissions. You need to set permissions, which is a fancy way of telling the server that you're authorizing the program to run there. You do this with the Unix command line. (See more about the Unix command line below if it's unfamiliar to you.) Check with your webhost to see what permissions they require. At Dreamhost you set permissions with chmod 755 for both your file and the directory it's in. If you rename the file you need to set its permissions again. If you delete the file from the server and then upload a fresh copy you need to set its permissions again. If you move it to another directory, you have to set the permissions at that new directory. 9. Run the script. There are four different ways to do this:
Notes: If your script is in a cgi-bin directory, don't forget to include that when typing the url. Embedding the reference in a web page: The whole page might look like this:<HTML> <BODY> <P>Here's the output from my program: <!--#include virtual="hello.cgi"--> </P> </BODY> </HTML> |
The
Unix Command Line
tutorial |
|||||||||||||
You'll use the Unix command line to set the permissions for your file, and possibly to test it for syntax errors. Check with your webhost to see what permissions they require. At Dreamhost you need to chmod 755 both your file and the directory it resides in. |
|||||||||||||
Where to get it |
Lucky for you, Unix command line interfaces come preinstalled with both Macs and Windows. On Mac OS X just open the Terminal application that's in Applications/Utilities on your hard drive. With Windows 98 go to Start > Run > c:\windows\telnet I'm not sure where it is in other versions of Windows, you may need to use the Find command. |
||||||||||||
Security |
There are two ways to connect to your webhosting account via the Unix command line: Telnet and SSH. Of these SSH is preferred because it's secure -- your password is encrypted so no one can pick it up as it makes its way through the Internet. The Mac OS X Terminal supports both Telnet and SSH. But Windows Telnet only does Telnet, not SSH. You can either use Telnet anyway, or look for SSH software for Windows. Go to download.com and search for "ssh". |
||||||||||||
Logging in |
You'll be using the same username & domain name combo that you use to upload your web files to your server. Do NOT include the www when typing your domain name. In the Mac OS X Terminal, type: ssh user@domain.com Then you're prompted for your password. In Windows Telnet: Go to Connect > Remote System. For host, put in your domain name WITHOUT the www. Then you'll be prompted to enter your username and password. |
||||||||||||
Unix commands |
Hooray, you've logged in. So now what can you do? Here are some basic commands
|
||||||||||||
Set permissions |
You'll use this command to set the permissions for your file. That's just a fancy way of saying that it makes the file authorized to run on your server. chmod 755 is specific to Dreamhost. Other servers may use something different. And for Dreamhost, even if the instructions that came with a preinstalled script tell you to use something besides 755, ignore it and use 755 anyway. For example, at Dreamhost, if your file is called myprogram.cgi and is in a directory called scripts then after logging in you'd type: cd mydomain.com chmod 755 scripts cd scripts chmod 755 myprogram.cgi |
Script
Basics |
|
The shebang line |
The first line of a script is called the shebang line. It should look like this: #!/usr/bin/perl -w usr/bin/perl tells the system where the Perl interpreter is located. The -w switch tells the interpreter to turn on Warnings about possible problems with your code. This will help you with your debugging. |
Special print command |
In plain Perl, all you have to do to print something is use the print command. But with Perl CGI for the web you have to include this line before your first print command: print "Content-type: text/html\n\n"; This is called an http header and tells the browser what kind of content it's about to get (in this case text/html, as opposed to, say, a cookie). If you don't include this then you'll get an Internal Server Error when you try to run it. The \n's are carriage returns. Don't worry, they won't add extra carriage returns to your outputted web page, they're just part of the http header (and necessary). Note that you print the header once, before your very first print command (not before every print command). Here's an alternate way to print: use CGI; $query = new CGI; print $query->h3('This is a headline.'); print $query->p('This is body text.'); |
Must include output |
Your script has to actually print some output or you'll get an Internal Server Error when you try to run it in a browser. This script would fail for that reason: #!/usr/bin/perl -w $variable="value"; You wouldn't get any errors when running it from the Unix command line, but it wouldn't work in a browser. The error in your error log would say, "Premature end of script headers." But this script would work: #!/usr/bin/perl -w $variable="value"; print "Content-type: text/html\n\n"; print $variable; Important! This seems so simple you'll be tempted to blow it off, because off course your program will have output, right? But here's how you'll run into it: You'll be getting some error because of something else, so you'll start stripping away parts of your program to test to see where the error is, to see if you've removed the offending code. Well you might remove the offending code *and* your only print statement, which fixes one problem and creates another. And don't count on a print statement that depends on an IF command. For safety's sake, put this line at the end of your code and keep it there until your development is done: print "Content-type: text/html\n\n"; |
TROUBLESHOOTING -- Those damn "Internal Server Errors" |
It seems like everything causes an error! I'm the most novice of novice programmers. And I had a hell of a time getting my Perl scripts to run in a browser without giving Internal Server Errors. I'd copy some simple example I found on the net, but it would never work. I'd write the simplest of programs, such as: #!/usr/bin/perl $variable="value"; and I'd still get an Internal Server Error! After a lot of effort finding out what causes the errors and how to correct them, I wrote this tutorial to share what I learned so your learning curve won't be as painful as mine was. That's why I wrote this article. Below is the summary of all the things I found that cause Internal Server Errors.
How to see the actual error, instead of "Internal Server Error"Put this code at the top of your script, and then when there's an error your browser will report the actual error: use CGI::Carp qw/fatalsToBrowser/; This will report syntax and logic errors, but not "bad file" errors. If you still get an Internal Server Error, then likely your file is not chmod 755, or it's missing the print header.
What to do when you have an Internal Server ErrorDon't panic. First of all, don't panic. When I first learned Perl CGI it seemed that all I got was Internal Server Errors and I felt like giving up. But I stuck with it and now I've been able to code all manner of useful things like rotating adverts and custom shopping carts. Stick with it, Perl works, you'll just have to do some tweaking. This troubleshooting guide will help. Run the file from the Unix command line If you get an Internal Server Error try running the file from the Unix command line, e.g.: perl -w hello.cgi Check the server log If you get an Internal Server Error in the browser but the script runs fine from the Unix command line, and your permissions are set correctly, and you can't find any problems with your output/print code, then you can see if there's a more detailed error listed in your server's error logfile. On Dreamhost servers the error log is at logs/domain.com/http/error.log. Note that the logs directory is at the very top level, above the directory for your html files. From the Unix command line, you can view the last error with the tail command. At Dreamhost the full command would be tail -f /home/username/logs/domain.com/http/error.log, substituting your own domain name for domain.com of course. Get rid of invisible garbage characters If you copy & paste code from a web page you might be copying invisible characters that kill your script (usually at the end of a line). Replace the existing returns & tabs by selecting them and typing fresh returns and tabs over them. Rebuild your script from scratch a few lines at a time If you've done everything above and you're still getting errors then you're probably pretty frustrated at this point. I know, I've been there. #!/usr/bin/perl -w print "Content-type: text/html\n\n"; print "Hello, world"; Upload it and run it. Just running something that actually works can give you some satisfaction and help restore your faith in Perl. (And if this doesn't work, your problem almost certainly one of the ones listed above under "Run the file from the Unix command line". Run the file from the command line to make sure.) |
Basic Perl Syntax tutorial |
This section assumes you have some familiarity with some other programming language. If you don't please see the references at the end of this page. Shebang line Unlike Java and C++, you don't have to put a whole bunch of crazy header commands in your script, nor do you have to make sure that something inside the script matches the filename. Just put this as your first line in your script and you'll be fine: #!/usr/bin/perl -w You don't have to close the file with anything special, either. Nor do you have to define classes or functions or procedures. (You can define functions if you want, but you certainly don't have to.) Just throw in the shebang line, add any more commands you want, and that's it. Lines end with semicolons Except for the shebang line, every command must have a semicolon at the very end. $thepoem = " My poetry is so beautiful it can annihilate penguins"; Assigning Variables You don't have to declare variables and you don't have to specify their type. The only thing special is that you have to put a $ before the variable name. $theText = "boo boo puppy"; $theTotal = 567; Comments The # sign indicates a comment, except in the shebang line. For example: $theText = "boo boo puppy"; # this is my string variable $theTotal = 567; # this is my number variable Numbers Numbers work the way they do in other languages $apples = 5; $bananas= 6; $total = $apples + $bananas; # add apples & bananas together $total = $total * 1.0825; # add sales tax $counter++; # add 1 to the counter Turning a string into an integer is easy: $size = int(size); Generating random numbers is also easy:$x = int(rand(5)); # returns an integer between 0 and 4, inclusive Strings Strings are enclosed with either single or double quotes. Double quotes tell Perl to include variables that have already been defined. $flavor = 'chocolate'; $food = "$flavor cookies"; print "I like $food."; # Prints "I like chocolate cookies." You can also combine strings with a period, though combining them as shown above is usually easier. $variable = 'Don\'t touch O\'Hara's \'snickerdoodle\'.'; But a better way is to use some other character to enclose your variable, by prefacing it with a q: $variable = q[Don't touch O'Hara's 'snickerdoodle'.]; In fact you can use any character you want, like q#...#, or q!...!. print qq[I like $food."]; Some more handy string functions:$theLength = length($variable); # number of characters in the variable $chop($variable); # removes last character $chomp($variable); # removes last character only if it's a Return Arrays Arrays are specified with the @ sign. @flavors = ('chocolate', 'strawberry', 'alarm clock'); And here's a shortcut to define arrays where each element is a single word: @flavors = qw(chocolate strawberry vanilla); Arrays are zero-based. (The first element is 0, not 1.) You refer to them just like in other languages: print $flavors[0]; # prints 'chocolate' $# returns the number of items in the array print $#flavors; # Returns 2; the length is zero-based, too Add and remove items to/from an array: shift(@array) # removes the first item pop(@array) # remove the last item unshift(@array,newelement) # adds to the beginning push(@array,newelement1,newelement2) # adds to the end For loops You can use for loops the same way you do in other languages: for ($counter=0; $counter<10; counter++) { [commands go here]; } But Perl has an easier way to do the same thing:: for $counter (0..10) { [commands go here]; } You can process every item in an array the same way: for $item (@myArray) { $item = "funky $item"; } This modifies the item in the array itself. |
I'm sorry, but I can't provide personal assistance with Perl. I have thousands of messages in my In Box as it is. I hope this tutorial helps you get off to a good start, though.
More resources:
Fan Mail
Your website was very helpful. I was seeing so many SERVER ERRORs that I was ready to use my wood maul as a debugging tool. -- Matt Alexander, June 2006
Last Update: June 2006