我不确定问题是与编程还是配置有关,如果我错了,请告诉我,我将重新在服务器配置相关堆栈上发布我的问题。
基本问题是:当我在终端中使用Perl执行这些脚本时,它完美地工作,但是当我在浏览器中使用mod_perl时,它会显示一些相当奇怪的行为。
来源 panelmin.pl
此程序仅输出一个消息,指示系统设备/dev/sda1是否已在系统中挂载。
#!/usr/bin/perl
use strict;
use warnings;
print "Content-type:text/html\n\n";
print "<html><head><title>USB test</title>";
print "</head><body>";
my $mounted = `df -h | grep /dev/sda1`;
if ($mounted eq '') {
print '<h1>USB device not connected</h1>';
print $mounted;
}
else {
print '<h1>Device is connected</h1>';
}
print '</body></html>';
umount.pl
该程序用于将系统中的/dev/sda1
设备卸载。
#!/usr/bin/perl
print "Content-type:text/html\n\n";
print "<html><head><title>Umount</title></head><body>";
system("sudo", "umount", "/dev/sda1");
print "</body></html>";
测试场景
Manually mounting the device
/dev/sda1
, (it is declared infstab
):$ mount -a
Making sure the device is mounted in the system:
$ mount /dev/sda1 on /mnt/usbstick type vfat (rw,relatime,uid=1000,gid=1000,fmask=0137,dmask=0027,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro)
Executing
panelmin.pl
in the web browser (I will use curl for the purpose of clean output):$ curl http://localhost/cgi-bin/admin/Q/panel/panelmin.pl <html><head><title>USB test</title></head><body><h1>Device is connected</h1></body></html>
As we can see, the output is correct. It detected the through linux command
df -h
that the device/dev/sda1
is mounted in the system.Executing
umount.pl
in the web browser in order to umount the device:$ curl http://localhost/cgi-bin/admin/Q/panel/umount.pl <html><head><title>Umount</title></head><body></body></html>
Verifying if the device is umounted using both
panelmin.pl
script in the web browser and linux command line.$ curl http://localhost/cgi-bin/admin/Q/panel/panelmin.pl <html><head><title>USB test</title></head><body><h1>USB device not connected</h1></body></html>
Seems to be correct, but let's verify it manually with
df -h
command:$ df -h | grep /dev/sda1 /dev/sda1 15G 366M 15G 3% /mnt/usbstick
As we can see the device is still mounted in the system.
Let's retry the whole process but this time instead of executing scripts in the browser we will launch them manually with
Perl
in the terminal. First lets umount the device. This will also show that the user is in sudoers and script can umount it.$ sudo umount /dev/sda1 $ df -h | grep /dev/sda1
Let's repeat the process.
$ mount -a (as superuser) $ df -h | grep /dev/sda1 /dev/sda1 15G 366M 15G 3% /mnt/usbstick
And finally the test:
$ perl panelmin.pl Content-type:text/html <html><head><title>USB test</title></head><body><h1>Device is connected</h1></body> $ perl umount.pl Content-type:text/html <html><head><title>Umount</title></head><body></body></html> $ perl panelmin.pl Content-type:text/html <html><head><title>USB test</title></head><body><h1>USB device not connected</h1></body></html> $ df -h | grep /dev/sda1
Now
df -h | grep /dev/sda1
returned empty string, it has proven thatumount.pl
managed to umount the device from the system, but only if executed in the shell withPerl
.
解决问题的尝试
确保在
umount.pl
中执行sudo umount /dev/sda1
的用户有权执行此操作,我通过在脚本中执行whoami
并将其打印在输出中进行了验证。尝试不同语法的
system()
,例如分离参数或作为一个命令执行。我验证了我的mod_perl是否以
taint mode
模式执行脚本,因为我听说它可能会影响执行外部进程。实际上,在我的httpd.conf
中没有PerlTaintCheck On
,如果我理解正确,它会影响使用动态参数执行(出于安全原因),对于我的脚本来说,每次都是相同的命令。我尝试使用不同的函数,用
Exec
或反引号替换System
等。我尝试使用
Apache2::SubProcess
,就像他们在这里所做的那样,但我必须承认,我不确定我是否做得正确,我是Perl的新手,这(以及所有其他可用的)示例都太糟糕了,例如他们的代码中从未初始化$r
变量,我只是将其声明为Apache2::RequestRec对象
,但它没有起作用。我尝试按照这里的说明更改环境变量,在子节
10.2.6. Starting a Long-Running External Program
中进行了说明。我验证了Apache目录中的日志,发现错误,但与这些脚本无关,我没有在此处发布它们,因为我不希望它变得太混乱。
解释
事实上,它在Perl
中运行而在mod_perl
中不运行并不令人惊讶,我认为最奇怪的是,在使用其system()
启动的panelmin.pl
脚本之后,执行umount.pl
后,它不再正确工作。目前我已经没有主意了,我认为这种行为很奇怪,我指望你们。希望有人知道我该怎么做。谢谢。
要求的结果
Capturing the output of System in
umount.pl
.#!/usr/bin/perl print "Content-type:text/html\n\n"; print "<html><head><title>Umount</title></head><body>"; my $res = `sudo umount /dev/sda1`; print "$res</body></html>";
And the result is void:
$ curl http://localhost/cgi-bin/admin/Q/panel/umount.pl <html><head><title>Umount</title></head><body></body></html>
system()
的返回值或使用use autodie qw(:all);
。 - mpapecsudo umount /dev/sda1 2>1
- Miller2>1
,用反引号捕获输出,输出与其他情况一样为空,并且我还使用Perl从shell执行了脚本并执行了命令本身,但没有输出。 - Marek