加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perl – 在Mojolicious中使用AnyEvent run_cmd,我不断收到此错误

发布时间:2020-12-16 06:28:04 所属栏目:大数据 来源:网络整理
导读:在一个Mojolicious应用程序中,我正在尝试在单击链接时将ODT文件转换为 HTML.我使用shell命令“soffice”转换文件.转换文件需要一些时间.我向用户发送状态消息以通知他进度.我通过写入Mojo :: Log对象发送这些状态更新消息.然后,我在EventSource路由中订阅此
在一个Mojolicious应用程序中,我正在尝试在单击链接时将ODT文件转换为 HTML.我使用shell命令“soffice”转换文件.转换文件需要一些时间.我向用户发送状态消息以通知他进度.我通过写入Mojo :: Log对象发送这些状态更新消息.然后,我在EventSource路由中订阅此日志对象.

然后我遍历文件并使用AnyEvent :: Util run_cmd来执行外部“soffice”程序.

for my $file (@{ $filelist }) {
   my $output_dir = './output_dir';
   my $cmd = "soffice --headless --convert-to html --outdir '$output_dir' '$file'";
   my $cv = AnyEvent->condvar;
   my $w;
   $w = run_cmd($cmd,'>'  => sub { my $out = shift;
                              &WriteToLog({ status => "cmd output '$out'..." });
                              undef $w;
                              $cv->send;
                 },'2>' => sub { my $err = shift;
                              &WriteToLog({ status => "ERROR '$err'..." });
                              undef $w;
                              $cv->send;
                 }
            );

   $cv->recv;
}

几乎从主要的AnyEvent教程中复制和粘贴.如果只有很少的文件要转换(大约2或3),那么一切顺利.通过EventSource连接发送的状态消息显示在客户端浏览器上.然后在转换完所有文件后,将呈现网页.

如果要处理更多文件,则会转换一些文件,然后会出现线程标题中的错误消息.

包含上述代码的路由的路由是:

my $initdocs = $r->under->to('docroute#initdocs');
$initdocs->get('/showdocs')->to('docroute#showdocs');

上面的代码是在“initdocs”路径中.

任何帮助表示赞赏.提前致谢.

解决方法

我认为你要做的是调用soffice(阻塞)进程而不阻塞服务器线程的其余部分.我不是AE的专家,但我认为这不是run_cmd的作用.它更接近fork_call的功能.也许你想要做的是更像这样的事情:

#!/usr/bin/env perl

use Mojolicious::Lite;
use EV;
use AnyEvent::Util 'fork_call';

any '/' => sub {
  my $c = shift;
  $c->render_later;
  fork_call { `sleep 5 && echo 'hi'` } sub {
    my $data = shift;
    $c->render( text => $data );
  };
};

app->start;

在我的例子中,我只是进行一个简单的阻止调用,但你可以很容易地调用到soffice.

现在,既然您说在返回客户端之前可能需要转换几个不同的文件,您可能需要使用优秀的Mojo::IOLoop::Delay来管理进程.

#!/usr/bin/env perl

use Mojolicious::Lite;
use EV;
use AnyEvent::Util 'fork_call';

my @jobs = (
  q{sleep 5 && echo 'hi'},q{sleep 5 && echo 'bye'},);

any '/' => sub {
  my $c = shift;
  $c->render_later;
  my $delay = Mojo::IOLoop->delay;
  $delay->on( finish => sub { 
    shift; $c->render(text => join '',@_ );
  });
  fork_call { `$_` } $delay->begin(0) for @jobs;
};

app->start;

再次,我只是捕获输出并将其发送到渲染调用,但请注意它在返回之前等待所有作业完成.更接近真实用例的可能是:

#!/usr/bin/env perl

use Mojolicious::Lite;
use EV;
use AnyEvent::Util 'fork_call';
use Capture::Tiny 'capture';

any '/' => sub {
  my $c = shift;
  my $files = $c->every_param('file');
  $c->render_later;
  my $delay = Mojo::IOLoop->delay;
  $delay->on( finish => sub { 
    shift; $c->render( json => @_ );
  });
  my $output_dir = './output_dir';
  for my $file (@$files) {
    my $cmd = "soffice --headless --convert-to html --outdir '$output_dir' '$file'";
    fork_call { [ capture { system $cmd } ] } $delay->begin(0);
  }
};

app->start;

这会在作为路径传递的每个文件名上运行soffice(/?file = myfile& file = otherfile).然后stdout,stderr和返回代码(好吧应该是,我显然没有运行这个)作为json呈现给客户端(你可以轻松地记录它).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读