如何使用shell脚本拦截perl脚本的执行然后实际执行它们?

时间:2017-03-09 19:54:34

标签: linux bash perl shell

问题有点复杂,首先我要告诉你情况。 我有一个包含许多域的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脚本:

perl script.pl

工作正常

但是如果我像这样从shell运行perl脚本:

./ script.pl

不行,错误看起来:

./ script.pl:line 3:print:command not found

我错过了什么?

1 个答案:

答案 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