Using Unix from Within Perl

Writing to a Process

Watch this: this is so cool:

   open(MAIL,"|/usr/lib/sendmail scotty@bluemarble.net");
   print MAIL "Subject: This is a subject line\n\n";
   print MAIL "This is an empty body.\n";
   close(MAIL);

What did that do? It wrote to a process rather than a file. That little pipe (|) on the first line tells any output to the filehandle MAIL to go to a sendmail process; when you close up the process, with the close statement--presto, you've sent yourself a mail message.

This is easily one of Perl's most powerful features. For instance, if you have a Perl script that generates a list of old files (at work, say) and the Internet addresses of the co-workers who own the files, you can send a message to every single one of them:


   while(....){
       ....
       open(MAIL,"|/usr/lib/sendmail $owner");
       print MAIL "Subject: Notification of Ancient Fileness\n\n";
       print MAIL "You own an ancient file named $ancientfile.\n";
       print MAIL "Would you like me to do anything about it?\n";
       close(MAIL);
   }

Yup: variables.

System Calls

A lot of the time, Unix can do something faster or easier than your Perl scripts can. Or maybe you just don't want to rewrite an entire program that Unix already provides... Perl enables you to execute a shell command from within a Perl program via the system() function: for instance, to allow a user to edit a file directly:
        
    system("/usr/bin/emacs $file")||die;

If you don't know what Emacs is, or aren't that familiar with Unix programs, then just forget you ever saw this section. Mostly it would just lead you to do extremely lazy shortcut things anyways.

Backticks

You can also fire up a shell process with the so-called 'backticks':

    @lines = `/usr/local/bin/lynx -source http://www.some-web-site.com`;

Now you have the front page of some website in an array, one line neatly stored in each array element. Imagine what you can do with that...
    @lines = `/usr/local/bin/lynx -source http://www.some-web-site.com`;
    foreach (@lines) {
        print if (/href/i);
    }
(And yes, you can write perfectly wonderful spiders, robots and web catalogs with Perl... Just, please, BE RESPONSIBLE. Read up on robot ethics before you even think about it.)

One important difference between a system() call and backticks: if you fire up a program with a line like this


    `/home/scotty/bin/some_program`;

then your original program won't wait until some_program is finished before hastening on to the next line. This can be quite powerful, but it's usually unnecessary and kinda scary until you get the hang of it. So to make sure that your original program waits obediently until some_program is finished up, do this:

    $result = `/home/scotty/bin/some_program`;

$result is a throaway value here; its only purpose is to force the original program to wait for some_program to exit.
Comments or suggestions? Please write scotty@bluemarble.net.