我在Perl中开发了一个简单的脚本,让我验证是否安装了USB密钥并最终卸载它。
我不确定问题是否与编程或配置有关,如果我错了请告诉我,我会在服务器配置相关堆栈上重新发布我的问题。
基本问题是:
当我使用Perl
在终端中执行这些脚本时,它工作得很好,当我在浏览器中使用mod_perl
时,它显示了一些非常奇怪的行为。
该程序只输出一条消息,指示系统设备/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>';
此程序从系统中卸载/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>";
手动安装设备/dev/sda1
,(在fstab
中声明):
$ mount -a
确保设备已安装在系统中:
$ 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)
在网络浏览器中执行panelmin.pl
(为了清洁输出,我将使用curl):
$ 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>
我们可以看到,输出是正确的。它检测到通过linux命令df -h
设备/dev/sda1
已安装在系统中。
在网络浏览器中执行umount.pl
以卸载设备:
$ curl http://localhost/cgi-bin/admin/Q/panel/umount.pl
<html><head><title>Umount</title></head><body></body></html>
使用网络浏览器和linux命令行中的panelmin.pl
脚本验证设备是否已安装。
$ 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>
似乎是正确的,但让我们使用df -h
命令手动验证它:
$ df -h | grep /dev/sda1
/dev/sda1 15G 366M 15G 3% /mnt/usbstick
我们可以看到设备仍然安装在系统中。
让我们重试整个过程,但这次不是在浏览器中执行脚本,而是在终端中使用Perl
手动启动它们。首先让我们卸载设备。这也将表明用户处于sudoers状态,脚本可以卸载它。
$ sudo umount /dev/sda1
$ df -h | grep /dev/sda1
让我们重复这个过程。
$ mount -a (as superuser)
$ df -h | grep /dev/sda1
/dev/sda1 15G 366M 15G 3% /mnt/usbstick
最后测试:
$ 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
现在df -h | grep /dev/sda1
返回空字符串,已证明umount.pl
设法从系统中卸载设备,但只有在Perl
的shell中执行。
确保在sudo umount /dev/sda1
中执行umount.pl
的用户有权这样做,我通过在脚本中执行whoami
并在输出中打印来验证它。 / p>
尝试system()
的不同语法,例如将参数分开或将其全部作为一个命令执行。
我验证了我的mod_perl是否在taint mode
中执行了脚本,因为我听说它可能会影响执行外部进程。事实上在我的httpd.conf
中没有PerlTaintCheck On
,如果我理解正确,它会影响执行动态参数(出于安全原因),在我的脚本的情况下,它是相同的命令每一次。
我尝试使用不同的功能,将System
替换为Exec
或反引号等。
我尝试使用Apache2::SubProcess
,就像他们here一样,但我必须承认我不确定我是否做得正确,我是Perl的新手(以及网上所有其他可用的)示例非常可怕,例如$r
变量从未在其代码中启动,我只是将其声明为Apache2::RequestRec object
,但它不起作用。
我尝试更改env变量,就像他们在10.2.6. Starting a Long-Running External Program
我在Apache目录中验证了日志,发现了错误但与这些脚本没有关系,我没有在这里发帖,因为我不想让它太乱了。
它适用于Perl
而非mod_perl
的事实并不令人惊讶,我发现最奇怪的是mod_perl
脚本panelmin.pl
似乎工作得很好使用它system()
启动并在执行umount.pl
后突然再次无法正常工作。现在我没有想法,我发现这种行为很奇怪,我依靠你们。我希望有人知道我该怎么做。感谢。
在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>";
结果是无效的:
$ curl http://localhost/cgi-bin/admin/Q/panel/umount.pl
<html><head><title>Umount</title></head><body></body></html>
答案 0 :(得分:0)
原来这个问题与编程没有关系,它与服务器配置有关。
这是Apache的错。它在多线程/多进程环境中工作。我不知道为什么,但这使他无法处理system()
函数。当我限制它在单一过程模式下工作时,问题就解决了。
即使知道问题与编程没有关系,我认为它应该留在这里,因为当这个问题发生时,可能很难确定问题的根源,我想StackOverflow将是第一个寻找大多数问题的地方初学者。