生成命令名和參數作爲數組,並傳遞至系統:
my(@command) = ("trash-put", 'home/$filename');
system @command;
這意味着,Perl不會調用殼做任何元字符膨脹(或I/O重定向,或命令管道或...)。它確實意味着它完全符合你的要求。
sub execute_command_error
{
system @_;
}
從評論的豐富收集借款信息:
這是perldoc -f system
或perldoc.perl.org/functions/system.html(@Ether)明確記載。
(參見「EXEC」的討論中緊密相關。)
您的意思是把$文件名中的單引號? (@mobrule)。
我沒打算用單引號 - 我證明了$filename
沒有得到通過Perl或殼牌擴大......在我的測試腳本中,我用「my.$file
」,這給了我一個文件一個$
的名字 - 正如我的意圖。
如果你想調用shell(例如,如果你想要一些管道),我認爲所需的引用是$ command_line =「\」$ command \「\」$ arg1 \「\」$ arg2 \ 「...」。 (@Jefromi)。
添加圍繞論點雙引號不會嵌入$
幫助,BACKTICK , '$(...)
' 及相關符號。你幾乎需要用單引號括起來,但是你需要重寫嵌入的單引號爲「'\''
」,它會生成一個單引號來終止當前的單引號參數,反斜槓引用組合代表一個單引號,而另一個單引號引用來恢復單引號的論點。
如果我直接使用系統命令,這將是一個很好的解決方案;但是我使用的是webmin的execute_command
函數,這在我的腦海中有點過分,所以我不知道如何編輯它以允許數組。你能否將嵌入式單引號的重寫擴展爲「'\''
」......這就是我現在要用的。(@Brian)
粗略地說,(Unix)shell處理單引號的方式是「從第一個單引號到下一個的所有內容都是文本文本,沒有元字符」。因此,爲了讓shell將某些東西當作文本文本來對待,請將它放在單個字符中。這涉及除單引號之外的所有內容。正如我的評論所說,你必須使用4個字符的替換字符串來將單引號嵌入單引號參數的中間。
有可能是一個更合適的方法來做到這一點比這(使用一個或兩個map
操作,也許),但這應該工作:
for (my $i = 0; $i < scalar(@command); $i++)
{
$command[$i] =~ s/'/'\\''/g; # Replace single quotes by the magic sequence
$command[$i] = "'$command[$i]'"; # Wrap value in single quotes
}
然後,您可以加入數組做一個字符串傳輸到execute_command
。
這是更好地寫,作爲系統{$命令[0]} @command來處理的情況下@command有一個元素。這是我在掌握Perl的「安全編程技術」一章中討論的內容之一。 (@briandfoy)。
作爲一般規則,我會接受此更正。不過,在這種情況下,我不確定它是否至關重要,其中命令名是由程序提供的,它只是可能提供給用戶的參數。命令名'trash-put'對於shell擴展是安全的(IFS在啓動時被shell重置爲默認值,因此攻擊途徑不可用)。
這個問題在'perldoc -f exec'手冊頁討論:
如果你真的不想要執行的第一個參數,但要騙你正在執行有關自己的名字的程序,你可以在LIST前面指定您實際想要作爲「間接對象」(不帶逗號)運行的程序。 (這總是迫使LIST的解釋作爲多值列表中,即使僅在列表中的單個標量。)
實施例:
$shell = '/bin/csh';
exec $shell '-sh'; # pretend it's a login shell
,或者更直接地,
exec {'/bin/csh'} '-sh'; # pretend it's a login shell
當參數獲得通過系統shell執行結果受其怪癖和能力的影響。有關詳細信息,請參閱perlop中的「STRING
」。
對exec或system使用間接對象也更安全。這種用法(對於system()也可以正常工作)強制將參數解釋爲多值列表,即使列表只有一個參數。這樣你就可以安全地從shell擴展通配符,或者用空格分開單詞。
@args = ("echo surprise");
exec @args; # subject to shell escapes
# if @args == 1
exec { $args[0] } @args; # safe even with one-arg list
第一個版本中,一個沒有間接對象,跑到回波程序,向它傳遞「驚喜」的參數。第二個版本沒有;它試圖運行一個名爲「echo surprise」的程序,沒有找到它,並設置$?指示失敗的非零值。
你怎麼背打勾在降價中顯示?
......在'perldoc -f system'中清楚地記錄了這一點:http://perldoc.perl.org/functions/system.html – Ether 2010-04-19 21:58:00
你是否想把'$ filename'放在單引號中? – mob 2010-04-19 22:00:09
我認爲所需的引用,如果你想要調用shell(例如,如果你想要一些管道)是'$ command_line =「\」$ command \「\」$ arg1 \「\」$ arg2 \「... 「'。 – Cascabel 2010-04-19 22:00:40