我之前从未遇到过这种情况,所以我可以使用一些帮助。我试图从shell命令发出if / else语句但在perl中。我试过系统和exec没有成功。这是代码示例
if ($os eq 'Ubuntu'){
system('if ! dpkg -l curl &> /dev/null; then apt-get install curl -y; fi');
foreach my $mod (keys %deb){
eval "use $mod";
if($@){
system("apt-get install $deb{$mod} -y");
eval "use $mod";
}
}
}
如果我在shell中运行命令if ! dpkg -l curl &> /dev/null; then apt-get install curl -y; fi
它可以正常工作,但是从perl执行它会跳过if
部分并继续安装它。
答案 0 :(得分:4)
if
完美无缺。
$ perl -e'system("if ! true ; then echo ok ; fi")'
$ perl -e'system("if ! false ; then echo ok ; fi")'
ok
但是有一个问题。您发布的是bash
命令,但system(EXPR)
是system('/bin/sh', '-c', EXPR)
的缩写。只需更换
system(EXPR)
与
system('/bin/bash', '-c', EXPR)
应该这样做。
答案 1 :(得分:2)
您可以避免深入了解if
语法的详细信息,并使用||
而不是否定来简化它。在命令行上试用它
perl -we 'system("rpm -q NO_PACK &> /dev/null || echo \"install package\"")'
我现在只能在RHEL上测试rpm
。但是,在RHEL上我发现这也可以正常工作
perl -we 'system("if ! rpm -q NO >& /dev/null ; then echo install; fi")'
命令中的语法与system
调用的shell冲突,后者在Ubuntu上是dash
(本身是sh
的链接)。感谢ikegami和ThisSuitIsBlackNot对此提出意见。特别是,重定向&>
不起作用,因为它具体是bash
的功能。然后,您可以更改为将> /dev/null 2>&1
流发送到STDOUT
的通用/dev/null
,并将STDERR
stream(2)重定向到STDOUT
(1)的同一位置去
system('dpkg -l curl > /dev/null 2>&1 || apt-get install curl -y');
在RHEL系统上,sh
是bash
的链接,因此&>
有效。请注意,2&>1
重定向也可以。但是,在我看来,更好的解决方案是指定要使用的shell。
system
允许一个人不通过在列表中提供参数来调用shell。然后直接运行作为第一个参数给出的程序,而不触发shell,并将列表的其余部分传递给它。这是获取正确的shell来运行命令的方法,因为您可以将shell指定为列表中的第一个参数。这在ikegami的答案中显示。
答案 2 :(得分:0)
这个问题似乎有点问题,所以我采用了另一种解决方法。这是我最终做的,它给了我相同的最终结果
if ($os eq 'Ubuntu'){
my $check = `dpkg --get-selections | grep "^curl *" | awk '{print \$1}'`;
if(!$check){ system('apt-get install curl -y > /dev/null'); }
foreach my $mod (keys %deb){
eval "use $mod";
if($@){
system("apt-get install $deb{$mod} -y");
eval "use $mod";
}
}
}