问题有点复杂,首先我要告诉你情况。 我有一个包含许多域的Web服务器,我想知道哪些perl脚本在每个域中运行用户以及使用哪些参数。
为此,我想到重命名perl,并创建一个名为perl的脚本,该脚本将环境保存在日志中,然后在perl中执行脚本
脚本非常简单,但显然有问题
#!/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
我使用一个简单的perl脚本来测试:
#!/usr/bin/perl
print "Working\n\n";
现在,问题 如果我从shell运行perl脚本:
工作正常
但是如果我像这样从shell运行perl脚本:
不行,错误看起来:
./ script.pl:line 3:print:command not found
我错过了什么?
答案 0 :(得分:7)
正如评论中所提到的,这可能是出于您的目的而过度杀戮,并且您可能会轻微破坏服务器上的每个Perl程序(例如,您传递的参数不正确)。您最好使用服务器日志或内核级别的内容,如lsof
。或者问问自己为什么需要知道用户正在运行哪些程序。
但了解发生了什么事情很方便。
#!
中的程序必须是已编译的可执行文件。它无法解释。 例如......
$ 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
正在执行的是test.pl
已执行且program loader看到了shebang line。然后检查它是否是可执行程序的绝对路径。不只是任何可执行文件,而是 可以直接由内核执行的 。
由于解释了/Users/schwern/tmp/notperl
,内核会忽略#!
行并将其交给shell执行。 shell没有print
函数,并告诉你。
通常用/usr/bin/env
解决这个问题。这是在修改后的环境中执行另一个程序的小程序。没有选项它只执行程序。
$ cat /Users/schwern/tmp/test.pl
#!/usr/bin/env /Users/schwern/tmp/notperl
print "Hello, world!\n";
$ /Users/schwern/tmp/test.pl
Hello, world!
在这种情况下,内核使用参数/usr/bin/env
执行/Users/schwern/tmp/notperl
。 /usr/bin/env
然后执行/Users/schwern/tmp/notperl
。