2

私はこのコードをcgiで持っています。

#!/usr/bin/perl
print "content-type: text/html \n\n";
print "<html><head><style>div.section{  font-size: 12px;    border: 1px solid #999999;  background-color: #EFEFEF;  margin: 10px 15px;}p{   font-family: \"Arial\", \"Helvetica\", \"sans-serif\";  font-size: 14px;    color: #444444; line-height: 30px;  margin: 0 10px 0 10px;  padding: 0 0 6px 0; text-align: center;}</style></head><body><div class=\"section\"><p>";
print "<b>YAMJ successfully updated your movie collection</b>";
print "</p><b>YAMJ output:</b><br>";
print "<pre>";
my $status = system("/usr/local/YAMJ/run.sh");
print "</pre>";
print "</div></body></html>";

コードは Synology の YAMJ のために MissileHugger によって作成されました。問題は、ユーザーが Synology でアプリを開くたびに、スクリプトが機能している間、空白のページが表示されることです。

その時点でスクリプトが行っていることのリアルタイムのデータ進行状況を出力する方法はありますか? Windows ソフトウェアをインストールするときと同様に、どのファイルがコピーされているかなどを示すステータスがあります。

私がこれを行うことができるかどうか誰にも分かりますか?

私の下手な英語でごめんなさい。

4

3 に答える 3

1

これは簡単にはできません。理由: HTTP はステートレスであり、ブラウザはページが完全にロードされた後にのみページをレンダリングできます。

   SERVER     COMMUNICATION  CLIENT
+------------+              +---------+
| Rendezvous | <----------- | Client  |
+------------+  get status  | Browser |
    ^              via      |         |
    | write     javascript  |         |
    | status                |         |
+------------+    invoke    |         |
|   Process  | <----------- |         |
+------------+              +---------+

使用できるアルゴリズムは次のとおりです。

  1. クライアント ブラウザが CGI スクリプトを要求します。これにより、長時間実行されるプロセスが開始されます。一意のセッション ID をブラウザに返します

  2. 長時間実行されるプロセスは、ランデブー ファイルをそのステータスで継続的に書き換えます。

  3. クライアントブラウザは、ID で指定されたランデブーファイルをポーリングし、javascript を使用して Web ページを更新します。HTML5 には、使用できる<progress>meter要素があります。

  4. セッションが終了すると、ファイルはサーバーのファイルシステムから削除されます。

最も単純なケースでは、継続的に書き換えられるページをブラウザで指定すると、ブラウザはそのページを数秒ごとにリロードするように指示されます。AJAX の時代には、これはほとんど時代遅れです。JavaScript 経由でのコンテンツの読み込みがよりスムーズになり、JSON 経由で複雑な状態を送信できるようになります。

{ "status": 0.4,
  "comments": ["loaded a file",
               "doing really hard math",
               "almost finished - just a moment please"]}

プレーンテキストの代わりに

Status: 40%

サーバーがこれらのイベントをブラウザーにプッシュするのは非常にエレガントですが、それを行う方法がわかりません。

于 2012-11-04T00:20:23.237 に答える
0

素晴らしいコード。解決策をありがとうございました。私は過去3日間これに取り組んできました..

これは、私のプログラムで機能するようにスクリプトを更新するために行ったことです。

#!/usr/bin/perl 

$|++; #This is needed to disable buffering

print "Content-type: text/html\r\n";
# This header is a quick hack which denies browser to gzip/deflate your output
print "Content-Encoding: plain\r\n\r\n";

&load_buffer; #This keeps the browser window printing progress as it's running

この時点から、プログラムの実行中に任意の print ステートメントが機能します。

例 テスト

for ($i = 1; $i < 11; ++$i)

{
print "$i<br>\n";

sleep(1);

}

サブルーチン

sub load_buffer {

my $cmd = qq{perl -e "\$|++; print ' ' and sleep(1) for 1..1"};
open my $PROC, '-|', $cmd or die $!;
while (sysread $PROC, $buffer, 1) { print "<!-- Browser shoudln't      cache this chunk ", ' ' x 1000, "-->\n";} 

}
于 2017-01-06T04:17:31.077 に答える
-1

STDOUTこれを実現するには、ファイルハンドルの自動フラッシュを有効にする必要があります。基本的に、次のコードをスクリプトの先頭 (シバンの後) に配置すると効果的です。

$|++;

自動フラッシュの詳細については、自動フラッシュの質問に関する以前の回答を参照してください。

次のワンライナーで違いがわかります。

perl -e "$|++; print '#' and sleep(1) for 1..10"
perl -e "print '#' and sleep(1) for 1..10"

PS: ターミナルで /usr/local/YAMJ/run.sh を実行すると、ASCII プログレス バーが表示されると思います。

更新:

これは機能するはずですが、次のようになります。

  1. 圧縮が有効になっている場合、Apache は出力を gzip し、単一のチャンクとして送信する場合があります
  2. ブラウザ(Chromeなど)のバッファ出力も。

したがって、いくつかの追加作業を実行する必要があります。

#!/usr/bin/perl

$|++;

print "Content-type: text/html\r\n";
# This header is a quick hack which denies browser to gzip/deflate your output
print "Content-Encoding: plain\r\n\r\n";

print "<html><body><h1>Start</h1>\n";

my $cmd = qq{perl -e "\$|++; print '#' and sleep(1) for 1..100"};

# Start your command, read it's output byte by byte
# and send it to the browser with a 1000+ bytes long comment
# which should prevent browser from caching just a single character
open my $PROC, '-|', $cmd or die $!;

my $buffer;
while (sysread $PROC, $buffer, 1) {
    print $buffer;
    print "<!-- Browser shoudln't cache this chunk ", ' ' x 1000, "-->\n";
}

print "<h1>Done</h1></body></html>";
于 2012-11-03T19:17:38.087 に答える