Reputation: 9
The question is a bit complicated, first I'm going to put you in situation. I have a web server with many domains and I want to know which perl scripts run the users in each domain and with which parameters.
For this I thought of renaming the perl, and create a script that is called perl that saves in a log the environment and then execute the script in perl
The script is very simple, but obviusly have something wrong
#!/bin/sh
when=`date "+%Y%m%d%H%M%S"`
log_file="/var/logs/perl/${when}"
env > log_file
parameters=$@
echo "Parameters: $parameters" >> $log_file
/usr/local/bin/perl_bin $parameters
I use a simple perl script to test:
#!/usr/bin/perl
print "Working\n\n";
Now, the problem If I run the perl script from the shell like this:
Works Ok
But If I run the perl script from the shell like this:
Don´t works and the error looks:
./script.pl: line 3: print: command not found
What am I missing ?
Upvotes: 0
Views: 156
Reputation: 164799
As mentioned in the comments, this is probably overkill for your purposes and you risk subtly breaking every Perl program on your server (for example, you're passing parameters incorrectly). You're better off using your server logs or something at the kernel level like lsof
. Or ask yourself why you need to know which programs your users are running at all.
But it's handy to understand what's going on.
The program in #!
must be a compiled executable. It cannot be interpreted. For example...
$ cat /Users/schwern/tmp/notperl
#!/bin/sh
perl "$@"
$ cat /Users/schwern/tmp/test.pl
#!/Users/schwern/tmp/notperl
print "Hello, world!\n";
$ /Users/schwern/tmp/notperl /Users/schwern/tmp/test.pl
Hello, world!
$ /Users/schwern/tmp/test.pl
/Users/schwern/tmp/test.pl: line 3: print: command not found
What's happening is test.pl
is executed and the program loader sees the shebang line. It then checks to see if that is an absolute path to an executable program. Not just any executable, but one that can be executed by the kernel directly.
Since /Users/schwern/tmp/notperl
is interpreted, the kernel ignores the #!
line and hands it off to the shell to execute. The shell has no print
function and tells you so.
One generally gets around this with /usr/bin/env
. This is a little program to execute another program in a modified environment. With no options it just executes the program.
$ cat /Users/schwern/tmp/test.pl
#!/usr/bin/env /Users/schwern/tmp/notperl
print "Hello, world!\n";
$ /Users/schwern/tmp/test.pl
Hello, world!
In this case the kernel executes /usr/bin/env
with the argument /Users/schwern/tmp/notperl
. /usr/bin/env
then executes /Users/schwern/tmp/notperl
.
Upvotes: 7