我想使用system()命令运行一些命令,我这样做:
execute_command_error("trash-put '/home/$filename'");
Run Code Online (Sandbox Code Playgroud)
如果运行的execute_command_error
任何system
命令出现错误,将在何处报告.我知道我可以使用Perl命令取消链接文件,但我想删除使用的东西,trash-put
因为它是一种回收程序.
我的问题是,$filename
有时会出现撇号,引号和其他奇怪的字符,这些字符会破坏system
命令或Perl本身.
生成命令名称和参数作为数组,并将其传递给系统:
my(@command) = ("trash-put", 'home/$filename');
system @command;
Run Code Online (Sandbox Code Playgroud)
这意味着Perl不会调用shell来执行任何元字符扩展(或I/O重定向,或命令管道,或......).它确实意味着它完全按照你的要求去做.
sub execute_command_error
{
system @_;
}
Run Code Online (Sandbox Code Playgroud)
从大量评论中借用信息:
这是在明确记载
perldoc -f system
或perldoc.perl.org/functions/system.html(@Ether).
(另见下面关于'exec'的讨论密切相关.)
你的意思是将$ filename放在单引号中吗?(@mobrule).
我确实打算使用单引号 - 我正在证明它$filename
不会被Perl或Shell扩展...在我的测试脚本中,我使用了' my.$file
',这给了我一个$
名字中带有a的文件- 就像我打算的那样.
我认为如果你想调用shell(例如,如果你想要一些管道),所需的引用是$ command_line ="\"$ command \"\"$ arg1 \"\"$ arg2 \"...".(@Jefromi).
在参数周围添加双引号对嵌入式$
,反引号1,$(...)
'和相关表示法没有帮助.你几乎需要单引号,但是你需要将嵌入的单引号重写为" '\''
",它会生成一个单引号来终止当前的单引号参数,一个反斜杠报价组合来表示单引号,另一个单引号恢复单引号参数.
如果我直接使用系统命令,这将是一个很好的解决方案; 但是我使用webmin的
execute_command
功能,这有点过头了,所以我不知道如何编辑它以允许数组.您是否可以将嵌入式单引号的重写扩展为"'\''
"......这就是我现在要使用的内容.(@布赖恩)
粗略地说,(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
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以加入数组以生成单个字符串以进行传输execute_command
.
最好将其写成系统{$ command [0]} @command来处理@command有一个元素的情况.这是我在Mastering Perl的"安全编程技术"一章中谈到的事情之一.(@briandfoy).
作为一般规则,我会接受这种更正.但是,我不确定在这种情况下它是至关重要的,其中命令名称由程序提供,并且它只是可能为用户提供的参数.命令名称'trash-put'对于shell扩展是安全的(shell启动时IFS将被重置为默认值,因此攻击途径不可用).
这个问题在'perldoc -f exec'手册页中讨论:
如果你真的不想执行第一个参数,但是想要对你正在执行的程序撒谎,你可以指定你真正想要作为"间接对象"(没有逗号)运行的程序列表的前面.(这总是强制将LIST解释为多值列表,即使列表中只有一个标量.)
例:
$shell = '/bin/csh';
exec $shell '-sh'; # pretend it's a login shell
Run Code Online (Sandbox Code Playgroud)
或者,更直接地,
exec {'/bin/csh'} '-sh'; # pretend it's a login shell
Run Code Online (Sandbox Code Playgroud)
当参数通过系统shell执行时,结果受其怪癖和能力的影响.有关
STRING
详细信息,请参阅perlop中的" ".使用带有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
Run Code Online (Sandbox Code Playgroud)
第一个版本,没有间接对象的版本,运行echo程序,将其"惊喜"传递给它.第二个版本没有; 它试图运行一个名为"echo surprise"的程序,没找到它,并设置$?到表示失败的非零值.
1如何在Markdown中显示后退?
归档时间: |
|
查看次数: |
1660 次 |
最近记录: |