重要:你應該總是檢查從Perl的system
函數的返回值,以確定該命令是否失敗。
使用Perl的sprintf
來格式化float值,如下面的代碼所示。是的,您可能能夠避免使用該命令作爲格式說明符,但如果該命令在其他地方存在零星字符,則可能會得到令人驚訝的結果。使用兩個步驟更安全。
#! /usr/bin/env perl
use strict;
use warnings;
my @float_values = (1.0e5, 3.14159, 2.71828);
for my $f (@float_values) {
my $arg5 = sprintf "%e", $f;
system(qq[./fermions $arg5 "string" >> outfile.out]) == 0
or warn "$0: fermions failed";
}
如果你不熟悉的語法,qq[...]
的作品就像一個雙引號字符串,但不同的分隔符意味着你不必在你的命令逃脫雙引號。
請注意,我爲了印刷目的而忽略了其他參數,但您可以將它們與值$arg5
一起插值。另一個微妙的變化是切換到>>
爲附加而不是>
進行破壞。
使用替身fermions
#! /usr/bin/env perl
$" = "][";
warn "[@ARGV]\n";
一起運行的兩個程序的輸出是
[1.000000e+05][string]
[3.141590e+00][string]
[2.718280e+00][string]
對於術語中,一個系統調用指的是用於一個低級別的請求來自操作系統的服務,例如,open
,close
,unlink
等等。雖然Perl的系統函數使用系統調用,但這兩個概念是不同的。
要成爲確實有關shell不會欺騙命令行參數的安全問題,請使用「Safe Pipe Opens」 section of perlipc中描述的技術。在給定參數列表時,Perl的system
和exec
函數繞過了shell,而不是包含整個命令的單個字符串。
你的情況有點棘手,因爲你想重定向標準輸出。下面的代碼將孩子分叉,將孩子的STDOUT
設置爲追加到outfile.out
,然後在兒童中運行fermion
和exec
。父母等待孩子退出並報告任何失敗。
#! /usr/bin/env perl
use strict;
use warnings;
my @float_values = (1.0e5, 3.14159, 2.71828);
for my $f (@float_values) {
my $arg5 = sprintf "%e", $f;
my $pid = fork;
if (defined $pid) {
if ($pid == 0) {
my $path = "outfile.out";
open STDOUT, ">>", $path or die "$0: open $path: $!";
exec "./fermions", $arg5, "string" or die "$0: exec: $!";
}
else {
local $!;
my $pid = waitpid $pid, 0;
warn "$0: waitpid: $!" if $pid == -1 && $!;
warn "$0: fermion exited " . ($? >> 8) if $?;
}
}
else {
die "$0: fork: $!";
}
}
請考慮使用'system LIST'或'system {PROGRAM} LIST' [invocation](http://perldoc.perl.org/functions/system.html)。當有一天,在許多重構之後,'$ arg2'變成'「; rm -rf /」',這將更加安全。您將無法使用shell輸出重定向,但您可以自己打開'outfile.out'並將其複製到STDOUT或將'。/ fermions'包裝在shell腳本中以捕獲輸出。 – pilcrow 2012-04-21 03:17:26
瞭解。我會爲此修改我的代碼,但我現在正在問這個問題以備將來使用。 – 2012-04-21 12:13:16