【问题标题】:Start a pdf viewer from a Perl script从 Perl 脚本启动 pdf 查看器
【发布时间】:2017-05-28 04:55:48
【问题描述】:

我必须从 Perl 脚本启动一个 pdf 查看器。观看者应 与父进程和运行父进程的终端分离。如果我关闭父母或终端 查看器仍应保持运行。我考虑了三种方法(使用evince 作为 pdf 查看器命令):

  1. 使用systemsh

    system 'evince test.pdf &';
    
  2. 使用fork()

    $SIG{CHLD} = "IGNORE"; #reap children as they complete
    my $pid = fork();
    if ( $pid == 0 ) {
        exec 'evince', 'test.pdf';
    }
    
  3. 使用Proc::Daemon

    use Proc::Daemon;
    my $daemon = Proc::Daemon->new(
        work_dir     => '/tmp/evince',
        child_STDOUT => '>>stdout.txt',
        child_STDERR => '>>stderr.txt',
    );
    my $pid = $daemon->Init();
    if ( $pid == 0 ) {
        exec 'evince', 'test.pdf';
    }
    

这些方法之间有什么区别?您会推荐哪种方法?

【问题讨论】:

    标签: perl daemon


    【解决方案1】:
    system 'evince test.pdf &';
    

    根据我的经验,这很可能是:

    system 'evince $pdf_file &';
    

    如果$pdf_file 是用户输入,那么我们会遇到shell 注入错误,例如传入$(rm -rf /) 的pdf 名称,甚至只是;rm -rf /。如果名称中有空格怎么办?好吧,如果你引用它,你可以避免所有这些,对吧?

    system 'evince "$pdf_file" &';
    

    嗯,不,现在我要做的就是给你一个文件名";rm -rf "/。如果我的 pdf 名称中有双引号怎么办?您可以使用单引号,但如果文件名中包含单引号,则会出现同样的问题,并且 shell 注入实际上并不难。您可以想出一个精心设计的 shellify 函数,该函数正确地引用一个字符串,以便 shell 可以取消引用它并返回到原始条目......但这似乎比您的其他选项工作量大得多,这两个选项都不会受到这些问题。

    $SIG{CHLD} = "IGNORE"; #reap children as they complete
    my $pid = fork();
    if ( $pid == 0 ) {
        exec 'evince', 'test.pdf';
    }
    

    设置一个全局的$SIG{CHLD} 很简单......除非你需要在其他孩子死去时处理他们。所以只有你才能判断这是否可以接受。而且,根据我的经验,甚至不是总是这样。我被这个咬过——虽然很少。我将它与在其他地方使用AnyEvent 的应用程序混合在一起,并设法破坏了 AE 的子进程处理。 (如果您将它与任何事件系统混合使用,可能也是如此,我只是碰巧使用了 AE。)

    此外,这缺少标准输出和标准错误重定向 - 以及标准输入重定向。这很容易添加 - 在您的 if 中,在执行之前,只需根据需要关闭并重新打开文件句柄,例如:

    close STDOUT; open STDOUT, '>', '/dev/null';
    close STDERR; open STDERR, '>', '/dev/null';
    close STDIN;  open STDIN,  '<', '/dev/null';
    

    没什么大不了的。但是,Proc::Daemon 确实为您设置了更多的东西,以确保信号不会从一个方向到达另一个进程。这取决于您需要得到的严重程度。

    对于我的大多数目的,我发现#2 就足够了。我只在几个项目中使用了 Proc::Daemon,但这就是 a) 我可以完全控制模块安装,b) 这真的很重要。启动 pdf 查看器通常不会是这种情况。

    我不惜一切代价避免使用 #1 - 我在 shell 注射方面有一些相当严重的咬伤,现在尽量避免使用 shell。

    【讨论】:

    • 如果这可能与nohupsetsid 命令有关会很有趣
    猜你喜欢
    • 2011-02-24
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 1970-01-01
    • 2014-07-10
    • 2011-12-04
    相关资源
    最近更新 更多