ページ 11

perlでカレントディレクトリ外のプログラムを起動する方法

Posted: 2013年1月13日(日) 02:32
by blade
perl初心者です。

プログラム内でカレントディレクトリでない場所のプログラムAを起動させてその出力結果を変数にコピーてその結果を1行ずつ処理したいと思っています。

とりあえずカレントディレクトリでない場所のプログラムAを起動させたいと思います。
まずプログラムAのある場所までパスを通せばいいのでしょうか。
そうだとしたらパスの通し方はどうやるのでしょうか。
ぐぐってもperlの設定時のパスの通し方ばかりで私の要求のものは見つけることができませんでしたのでここで質問させていただきます。

現段階のコードです

コード:

#!c:/perl/bin/perl.exe

use strict;
use CGI;
use CGI::Carp qw(fatalsToBrowser);

our $return_value;
our @lines
our @line


#パスを通してから?
$return_value = 'xxx.bat  < aaa.txt'
#print $return_value;

@lines = split(/\n/ $return_value);  #プログラムAの出力を改行で区切ります
foreach my $line ( @lines ) {
# 一行ずつ処理
print $return_value;
print "\n";
}	
16行目以降はウェブ上にあったのを適当にコピペして変数を変えたりしたのみですので、
おそらく間違っていると思います。

Re: perlでカレントディレクトリ外のプログラムを起動する方法

Posted: 2013年1月13日(日) 05:21
by トントン
まず、指摘から。
①シンタックスエラーから直しましょう。
perlも行の終わりに必ず「;」が必要です。
(正確には入らない箇所もあるんですけどね)

②split関数の引数
split関数は引数が「2つ」以上必要です。

③@line
$lineも宣言していることですし、@lineは使用されていないようなので消してしまいましょう。

で、質問の件ですが
Perlもファイルへのパスの指定はCと変わりません。
「./a/b/c.txt」や「.\\a\\b\\c.bat」などで指定できます。

コード:

          .-----------.
          |current dir|
          `-----------'
     .----------+-----------.
.---------. .--------. .---------.
|index.cgi| |list.txt| |batfolder|
`---------' `--------' `---------'
                            |
                        .--------.
                        |test.bat|
                        `--------'
また、上記のような構成の場合、
以下のようにして、出力することが可能です。

コード:

open my $fh, '.\\batfolder\\test.bat list.txt|';
while ($line = <$fh>) {
	print "$line\n";
}

# ローカル鯖で実施しているんですよね?

Re: perlでカレントディレクトリ外のプログラムを起動する方法

Posted: 2013年1月13日(日) 07:00
by blade
ローカルサーバで実施しています。

シンタックスエラーはなくなったのですが、
データを受信していません
と表示されてしまいました。

コード:

#!c:/perl/bin/perl.exe

use strict;
use CGI;
use CGI::Carp qw(fatalsToBrowser);

my $line;

open my $fh, 'C:\\Users\\blade\\Desktop\\xxx.bat  <aaa.txt';
while ($line = <$fh>) {
    print "$line\n";
}
Destopにあるxxx.batにaaa.txtをリダイレクトしたい場合は以上のようでよろしいのでしょうか。

Re: perlでカレントディレクトリ外のプログラムを起動する方法

Posted: 2013年1月13日(日) 08:31
by みけCAT
CGIでしたら、データを出力し始める前に

コード:

print "Content-type: text/plain\n\n";
などのMIME表記が必要です。
blade さんが書きました:

コード:

#!c:/perl/bin/perl.exe

use strict;
use CGI;
use CGI::Carp qw(fatalsToBrowser);

my $line;

open my $fh, 'C:\\Users\\blade\\Desktop\\xxx.bat  <aaa.txt';
while ($line = <$fh>) {
    print "$line\n";
}
Destopにあるxxx.batにaaa.txtをリダイレクトしたい場合は以上のようでよろしいのでしょうか。
これだと、「xxx.batの標準入力をaaa.txtにリダイレクトし、出力は読み込まない」となっています。

コード:

open my $fh, 'C:\\Users\\blade\\Desktop\\xxx.bat  <aaa.txt |';
とすれば標準出力を読み込めます。
また、openしたファイルハンドルはcloseするべきではないでしょうか?
そして、<ファイルハンドル>で読み込んだデータには改行がくっついていることが多いので、
最後の改行文字が不要ならchompで取り除けます。
以上の点を踏まえると、このような感じになります。

コード:

#!/usr/bin/perl

use strict;
use CGI;
use CGI::Carp qw(fatalsToBrowser);

my $line;

print "Content-type: text/plain\n\n";

open my $fh, 'C:\\Users\\blade\\Desktop\\xxx.bat  <aaa.txt |';
while ($line = <$fh>) {
	chomp($line);
    print "$line\n";
}
close($fh);

Re: perlでカレントディレクトリ外のプログラムを起動する方法

Posted: 2013年1月13日(日) 09:40
by blade
いろいろ不足していてすみません。

コード:

#!/usr/bin/perl
 
use strict;
use CGI;
use CGI::Carp qw(fatalsToBrowser);
 
my $line;
 
print "Content-type: text/plain\n\n";

open my $fh, 'C:\\Users\\blade\\Desktop\\xxx.bat  < C:\\Users\\blade\\Desktop\\aaa.txt |';


while ($line = <$fh>) {
    chomp($line);
    print "$line\n";
}
close($fh);
ちゃんと動いているようなのですが、11行目の時点でコマンドプロンプトが出てきてその中でプログラムが起動したようなのですが
そのプログラムが終了せず、結果この.cgiプログラムも終わらずブラウザではずっと読み込み状態が続いたままになります。

直接コマンドプロンプトで
C:\\Users\\blade\\Desktop\\xxx.bat < C:\\Users\\blade\\Desktop\\aaa.txt
を入力すると正しく起動して終了するのですがどうしてperlで書いたプログラム内だと終了しないのでしょうか。

Re: perlでカレントディレクトリ外のプログラムを起動する方法

Posted: 2013年1月13日(日) 09:52
by みけCAT
答えになっていませんが、間違えてしまってすみません。
1行目のパスは

コード:

#!c:/perl/bin/perl.exe
のままでいいはずです。

バッチファイルの中身を見せてもらうことはできませんか?

Re: perlでカレントディレクトリ外のプログラムを起動する方法

Posted: 2013年1月14日(月) 10:23
by blade
すみません、1行目勝手に変えてしまっていたようです。戻しました。

以下バッチファイルの中身です。よろしくお願いします。

コード:

REM  mogura.bat
REM
REM  batch script to run mogura.exe.
REM
REM ################################################################################

SETLOCAL

SET CURRENT_DIR=%CD%

REM SET BASE_DIR=%~dp0
SET BASE_DIR=..

REM set environment variables
SET ENJU_WIN=1

IF NOT DEFINED ENJU_PREFIX (
	SET ENJU_PREFIX=%BASE_DIR%
)

IF NOT DEFINED ENJU_DIR (
	SET ENJU_DIR=%BASE_DIR%\lib\enju
)

IF NOT DEFINED LILFES_PATH (
	SET LILFES_PATH=%BASE_DIR%\share\liblilfes
) ELSE (
	SET LILFES_PATH=%BASE_DIR%\share\liblilfes;%LILFES_PATH%
)

REM SET BIN_DIR=%BASE_DIR%\bin
SET BIN_DIR=%~dp0\bin
CD %BIN_DIR%

SET COMMAND=mogura.exe

CMD /c %COMMAND% %*

CD %CURRENT_DIR%

ENDLOCAL
@ECHO ON


Re: perlでカレントディレクトリ外のプログラムを起動する方法

Posted: 2013年1月15日(火) 00:34
by トントン
※一応言っておくとバッチファイルは正直わからんです。

バッチファイルはこちらでは使用できないんですね。

コマンドプロンプトが起動して止まるということは
バッチ処理かmogura.exe(を起動しているのかな?)が
正しく起動できていないのかなと思います。
バッチ処理の何処まで起動できているか確認できますか?
また、取りえる値は正しく設定されていますか?

# 簡単なものから取り組むのが良いかなぁと思いますけどね。
# どうでも良いけどパイプコマンドも第3引数まで指定できたんですね。
# open my $fh, '-|', '$command or open my $fh, '|-', '$command'

Re: perlでカレントディレクトリ外のプログラムを起動する方法

Posted: 2013年1月15日(火) 15:13
by blade
トントン さんが書きました: コマンドプロンプトが起動して止まるということは
バッチ処理かmogura.exe(を起動しているのかな?)が
正しく起動できていないのかなと思います。
バッチ処理の何処まで起動できているか確認できますか?
タスクマネージャを見るとmogera.exeは起動していましたが、終了していませんでした。
おそらく35行目で止まっているのだと思います。
トントン さんが書きました: また、取りえる値は正しく設定されていますか?
取り得る値とは何の値でしょうか。
一応設定は正しくできています・
ちなみにコマンドは
'C:\\Users\\blade\\Desktop\\xxx.bat < C:\\Users\\blade\\Desktop\\aaa.txt |
で、最後の縦線を除いたものを入力すると確かに正しく動き正常終了します。

Re: perlでカレントディレクトリ外のプログラムを起動する方法

Posted: 2013年1月16日(水) 00:04
by トントン
とりえる値とは
バッチファイル内で、setしているであろうパスや
移動したディレクトリのパスなどのことです。
コマンドプロンプトでは正常に動いていても
Perl、もしくはCGIで動かすことによって上手く動いていないのかもしれません。
(おそらくmogura.exeにtxtファイルを渡す前に前設定をしているのですよね?
mogura.exeに設定する内容?やtxtファイルはちゃんと渡せているのかなぁと)

また、以下の確認をお願いします。
・他のバッチファイル及び、exeファイルではどうなるのでしょうか?
・一応、環境を教えてもらってもよろしいでしょうか? (ブラウザ、開発環境など)
・用意できるのであれば、再現できるバッチファイルとexe(可能ならソース または処理内容)を用意していただけますか?
・これは、興味本位なのですが「コマンドプロンプトが出てきてその中でプログラムが起動したようなのですが」というのは最初のバッチファイルなのかmogura.exeどちらなのでしょうか?

再現できる環境がないので、申し訳ないですが時間がかかりそうです。

Re: perlでカレントディレクトリ外のプログラムを起動する方法

Posted: 2013年1月16日(水) 00:31
by softya(ソフト屋)
情報はechoで出せるので表示させてみたらどうでしょうか?
あと縦線ってパイプ機能なので後ろに何も書かないとエラーだと思います。