IPC::Open3 - 使用 open3() 開啟程序以進行讀取、寫入和錯誤處理
use Symbol 'gensym'; # vivify a separate handle for STDERR
my $pid = open3(my $chld_in, my $chld_out, my $chld_err = gensym,
'some', 'cmd', 'and', 'args');
# or pass the command through the shell
my $pid = open3(my $chld_in, my $chld_out, my $chld_err = gensym,
'some cmd and args');
# read from parent STDIN
# send STDOUT and STDERR to already open handle
open my $outfile, '>>', 'output.txt' or die "open failed: $!";
my $pid = open3('<&STDIN', $outfile, undef,
'some', 'cmd', 'and', 'args');
# write to parent STDOUT and STDERR
my $pid = open3(my $chld_in, '>&STDOUT', '>&STDERR',
'some', 'cmd', 'and', 'args');
# reap zombie and retrieve exit status
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;
與 open2() 極為相似,open3() 會產生指定的命令,並連接 $chld_out 以從子程序讀取,連接 $chld_in 以寫入子程序,並連接 $chld_err 以處理錯誤。如果 $chld_err 為 false,或與 $chld_out 為同一個檔案描述符,則子程序的 STDOUT 和 STDERR 會在同一個檔案處理程序上。這表示無法對 STDERR 檔案處理程序使用自動變數,但可以從 Symbol 使用 gensym 來變數化新的 glob 參照,請參閱 "語法"。$chld_in 會開啟自動快取。
如果 $chld_in 以 <&
開頭,則會在父程序中關閉 $chld_in,而子程序會直接從中讀取。如果 $chld_out 或 $chld_err 以 >&
開頭,則子程序會將輸出直接傳送至該檔案處理程序。在兩種情況下,都會進行 dup(2),而不是 pipe(2)。
如果讀取器或寫入器為空字串或未定義,這將會被自動產生的檔案處理器取代。如果是這樣,您必須在參數槽中傳遞一個有效的左值,以便可以在呼叫者中覆寫它,否則將會引發例外。
檔案處理器也可以是整數,在這種情況下,它們被理解為檔案描述符。
open3() 傳回子程序的程序 ID。它不會在失敗時傳回:它只會引發符合 /^open3:/
的例外。但是,子程序中的 exec
失敗(例如沒有此類檔案或拒絕存取權限),只會在 Windows 和 OS/2 中報告給 $chld_err,因為無法攔截它們。
如果子程序因任何原因而終止,下一次寫入 $chld_in 時可能會在父程序中產生 SIGPIPE,這在預設情況下是致命的。因此,您可能希望處理這個訊號。
請注意,如果您指定 -
作為命令,類似於 open(my $fh, "-|")
,子程序將只是分岔的 Perl 程序,而不是外部命令。此功能尚未在 Win32 平台上受支援。
open3() 在子程序退出後不會等待並收割它。除了可以讓作業系統處理的短程式之外,您需要自己執行此操作。這通常只要在處理完程序後呼叫 waitpid $pid, 0
即可。未能執行此操作可能會導致累積已失效或「僵屍」程序。請參閱 perlfunc 中的「waitpid」 以取得更多資訊。
如果您嘗試從子程序的 stdout 寫入器和 stderr 寫入器讀取,您將會遇到封鎖問題,這表示您會想要使用 select() 或 IO::Select,這表示您最好使用 sysread() 而不是 readline() 來進行一般事務。
這非常危險,因為您可能會永遠封鎖。它假設它會與類似 bc(1) 的東西交談,同時寫入和讀取它。這可能是安全的,因為您「知道」像 bc(1) 這樣的命令一次會讀取一行,並一次輸出。然而,像 sort(1) 這樣的程式會先讀取其整個輸入串流,很可能會造成死結。
此方法的一大問題是,如果您無法控制在子處理序中執行的原始碼,您就無法控制它使用管線緩衝區的方式。因此,您不能只對 cat -v
開啟管線,並持續讀取和寫入一行。
類似於 Open3,但沒有 STDERR 擷取。
這是一個 CPAN 模組,它具有比 Open3 更好的錯誤處理和更多功能。
參數的順序與 open2() 不同。