我可以在命令行上执行以下脚本。 回声&#34; 56.8 + 77.7&#34; | bc -l </ p>
我也得到了正确的输出但是当我尝试在我的perl / html脚本中执行相同操作并在浏览器中运行它时失败了。你能指导我出错吗?
package core.framework.zookeeper;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
public class ZkConnect {
private ZooKeeper zk;
private CountDownLatch connSignal = new CountDownLatch(0);
//host should be 127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002
public ZooKeeper connect(String host) throws Exception {
zk = new ZooKeeper(host, 3000, new Watcher() {
public void process(WatchedEvent event) {
if (event.getState() == KeeperState.SyncConnected) {
connSignal.countDown();
}
}
});
connSignal.await();
return zk;
}
public void close() throws InterruptedException {
zk.close();
}
public void createNode(String path, byte[] data) throws Exception
{
zk.create(path, data, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
public void updateNode(String path, byte[] data) throws Exception
{
zk.setData(path, data, zk.exists(path, true).getVersion());
}
public void deleteNode(String path) throws Exception
{
zk.delete(path, zk.exists(path, true).getVersion());
}
public static void main (String args[]) throws Exception
{
ZkConnect connector = new ZkConnect();
ZooKeeper zk = connector.connect("54.169.132.0,52.74.51.0");
String newNode = "/deepakDate"+new Date();
connector.createNode(newNode, new Date().toString().getBytes());
List<String> zNodes = zk.getChildren("/", true);
for (String zNode: zNodes)
{
System.out.println("ChildrenNode " + zNode);
}
byte[] data = zk.getData(newNode, true, zk.exists(newNode, true));
System.out.println("GetData before setting");
for ( byte dataPoint : data)
{
System.out.print ((char)dataPoint);
}
System.out.println("GetData after setting");
connector.updateNode(newNode, "Modified data".getBytes());
data = zk.getData(newNode, true, zk.exists(newNode, true));
for ( byte dataPoint : data)
{
System.out.print ((char)dataPoint);
}
connector.deleteNode(newNode);
}
}
我也尝试使用系统,但似乎没有用。
答案 0 :(得分:4)
好的,所以bc
是一个unix实用程序,可以让你做数学运算。您可以通过qx
运算符或反引号执行实用程序命令。
然而,在这种情况下......这是一个坏主意,因为它是a)不必要的,b)存在安全风险。为什么?因为您将用户输入从Web表单传递到shell中,从而为您提供了一系列注入攻击。
为什么不改为:
my $res = 56.8 + 77.7;
虽然你在这里,但你真的应该:
use strict;
use warnings;
-T
)。 这将减少通过代码注入发生“坏事”的可能性。当你打开“污点”模式时,它会在“污染”时标记任何用户输入,并且不会让你将它用于某些命令而不先清理它。
作为一个例子 - 想象一下如果有人输入了一个表达式:
4"; rm -rf /; echo "owned
然后你会得到评价它的反对意见;
echo "4";rm -rf /; echo "owned" | bc -l
我想你可以看到这将是一个坏消息!
所以你真的不应该 - 通过用户输入来执行这样的操作。你也应该对eval非常谨慎。使用正则表达式确保您的操作本质上只是“数学”:
unless ( $str =~ /[^0-9+-*^/.,_()]/ ) {
eval ( $str );
}
(为此目的,也可能存在模块)
或者:
my $eval_str = "5 + bogus; nonsense; here 210";
$eval_str =~ s{[^0-9\+\-\/\=\/]+}{}g;
print $eval_str;
答案 1 :(得分:0)
正如其他人所指出的那样,你可以在Perl中进行计算。无需拨打bc
。
但是我希望看一下你产生输出的方式。你正在使用大量的print()
语句。还有更好的方法。
首先,你的陈述如下:
print "<table border=\"0\">\n";
我知道你为什么会有反斜杠,但它看起来不丑陋吗?出于显而易见的原因,您需要在双引号字符串中转义双引号字符。但对于这样的情况,Perl有qq[...]
运算符:
print qq[<table border="0">\n];
qq[...]
就像双引号字符串一样,但因为它不使用双引号字符来分隔字符串,所以不需要转义字符串中的双引号字符。请注意,您甚至不需要使用[...]
来分隔字符串。您几乎可以使用任何字符 - qq(...)
,qq|...|
以及许多其他选项。
其次,为什么每行都有一个单独的print()
语句。什么不将它们组合成一个print()
语句?
print qq[Content-Type: text/html
<html><body>
<b>Calculator:</b><br/>
<form action="/cgi-bin/calc.cgi" method="GET">
<table border="0">
<tr><td align="right">Expression:</td>
<td><input type="text" name="exp"
value="$exp"/></td></tr>
<tr><td align="right">Result:</td>
<td>$res</td></tr>
<tr><td></td>
<td><input type="submit" value="Evaluate"/></td></tr>
</table></form>
</html></body>];
请注意如何丢失所有显式\n
并将其替换为字符串中嵌入的实际换行符。那看起来不整洁吗?
事实上,大多数Perl程序员都会更进一步,并使用“heredoc”:
print <<"ENDHTML";
Content-Type: text/html
<html><body>
<b>Calculator:</b><br/>
<form action="/cgi-bin/calc.cgi" method="GET">
<table border="0">
<tr><td align="right">Expression:</td>
<td><input type="text" name="exp"
value="$exp"/></td></tr>
<tr><td align="right">Result:</td>
<td>$res</td></tr>
<tr><td></td>
<td><input type="submit" value="Evaluate"/></td></tr>
</table></form>
</html></body>
ENDHTML
另外,请考虑使用CGI模块的header()
方法创建Content-Type标头。
最后,您可以查看CGI::Alternatives以了解如何将所有HTML移到单独的文件中。
答案 2 :(得分:0)
IPC :: Run3和IPC :: Run可以轻松地为子进程提供输入和收集输出。
use IPC::Run3 qw( run3 );
my $equation = '56.8 + 77.7';
run3([ 'bc', '-l' ], $equation, \my $stdout, \my $stderr);
这种方法的好处:
不涉及shell,避免了意外shell代码注入的可能性。
Perl的eval
并未涉及,这避免了意外Perl代码注入的可能性。
无需编写自己的方程解析器。