2013-11-25 69 views
5

我在Windows上運行一個Perl腳本,調用可執行文件:Perl的命令行解釋不出來

$command = "$path_to_exe -i $dir -o $results"; 
my $pid = fork(); 

    if (!$pid) { 
     system($command); 

     #do stuff 

    } else { 
     #do stuff 
    } 

print "Exiting..." 
exit; 

代替後退出的,只是perl.exe所在空轉。然後彈出窗口告訴我,「Perl命令行解釋器已停止工作。」

我不知道很多有關Windows進程管理,我已經在這個論壇上,它不是使用fork()exec()好的做法以前讀,但代碼工作得很好,除了解釋不打烊的一部分。我嘗試了一切,從嘗試在Unix中執行程序(這給出了相同的錯誤),使用Win32::Process命令 - 但沒有任何工作。我希望有一個更簡單的解決方案可以讓我保留我已經寫的東西。

如果任何人都可以解釋這個代碼運行時在Windows中究竟發生了什麼,那也是一種幫助!

+0

叉EXEC不上贏得良好的習慣,因爲勝利是不是優化它。 Win是對海量線程和本地rpc進行了優化。但在你的情況下,這不是一個真正的問題,因爲你並不重要,你的包裝腳本0.001s或0.01s的開銷產生。如果你有例如一個數據庫服務器守護進程或者每秒必須被調用一千次的東西,它纔是重要的。另一件事,是的,fork() - exec()很慢,但fork() - system()更慢......我進一步看到,你根本沒有對第二個問題做出反應($ pid和不是$$)。你應該是合作者。 – peterh

回答

4

我可以看到2個獨立的問題。

  1. system()創建一個子進程,因此,如果您調用從分叉孩子system(),你將有3個過程。但是你只殺死第二個(分叉的孩子),而不是孩子的孩子($命令)。嘗試使用一些像exec()這樣的函數,在unix上它會在實際進程的地方(和pid上)啓動子進程。如果你有運氣,Windows上的Perl也是一樣的。

  2. 你殺死的父線程$$,這是當前進程。可能你想殺死$pid(這是父線程上子進程的pid)。

+0

我用exec()進行了實驗,發現它也不會退出。我會再試一次,看看會發生什麼。窗口中的$ pid不是子進程的'$ pid',而是一個負數,我認爲它對應於一個「僞過程」。不知何故,我使用'taskkill'的方式是有用的,不要問我如何。謝謝 – user86895

+0

我認爲你的生存方式是,如果你停止盲目拍攝,並開始瞄準你的手和眼睛。 – peterh

1

我用下面(超時程序,最重要的是,不破Perl解釋器!):

use Win32::Job; 
my $job = Win32::Job->new; 

    # Run $command for $max_time 
    $job->spawn($Config{"path/cmd.exe"}, $command); 
    $job->run($max_time); 
    exit; 
1

在我來說,我刪除了一些「使用」的語句和它被解決了。 這可能是因爲Windows上「fork」的perl實現並不完美,並且導入某些「重」對象(如OLE庫)時出現問題。

的確切用途,我刪除:

#use Win32::OLE qw(in with); 
#use Win32::OLE::Const 'Microsoft Excel'; 

解決方法:如果可能的話,儘量點後動態庫進口有代碼中沒有叉子。

示例我的情況:

# code with fork 
eval "use Win32::OLE::Const 'Microsoft Excel';"; 
eval "use Win32::OLE qw(in with);"; 
# code without fork