DOS Line endings break CGI script execution

Some fellows in another office asked for help figuring out why the CGI script they were writing wouldn’t run.

Yesterday, I’d helped them find that the interpreter named on the she-bang line (#!) of their scripts didn’t exist and I’d recommended they use “#!/usr/bin/env perl” instead.  They did, but wrote the test.cgi script in notepad and then transfered the file to the Linux web server with something that left the DOS line endings intact.

So, when Apache tried to run the script, the /usr/bin/env program got handed “perl^M” instead of “perl,” couldn’t find that in the path anywhere and blew chunks.  Here’s what I wrote back to explain:

The problem exists when you use /usr/bin/env to invoke the interpreter and pass it a string (the interpreter name) on the command line and that string ends in a trailing ^M.  That ^M is the part of the DOS line ending that dos2unix would remove.  So, in your simpletest.cgi script, this is what Unix is seeing as the top line:

#!/usr/bin/env perl^M

So, the /usr/bin/env program is trying to invoke a program named “perl^M”, which doesn’t exist.  If you’d like to have some fun with this, make a symlink from /usr/bin/perl to /usr/bin/perl^M and watch your program run.  🙂
(Make the ^M by pressing CTRL-V and then either CTRL-M or <ENTER>.)
In your new file listdocs2011, you won’t see this problem crop up because the line looks like this:
#!/usr/bin/env perl -w ^M

In this line, you have a space after the -w switch.  You won’t see it in notepad, but it’s there.  And it’s what allows that script to run with the CGI.  Because /usr/bin/env is getting “perl” and “-w” and “^M” as three separate words on the command line.  It knows what to do with the first two and perl get the ^M, which it probably ignores.
If there were my mess to clean up, I’d probably use grep -l ‘^M$’ to list the names of files that have the problem and then run dos2unix on just those file names:
In bash:   dos2unix $(grep -l ‘^M$’) But remember, that ^M is made with the CTRL-V and then CTRL-M.  Not the ^ and the M keys.

 

Leave a Reply

You must be logged in to post a comment.