.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. | will give a .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' .\" expand to `' in nroff, nothing in troff, for use with C<>. .tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "PERLFAQ8 1" .TH PERLFAQ8 7 "2003-11-25" "perl v5.8.3" "Perl Programmers Reference Guide" .SH "NAME" perlfaq8 \- 系統交互 (2003/01/26 17:44:04 ) .SH "DESCRIPTION 描述" .IX Header "DESCRIPTION" Perl FAQ 的這一節覆蓋了與系統交互有關的問題。主題包括進程間通信 (IPC),用戶界面控制 (鍵盤,屏幕和指點設備),以及其他與數據操作不相關的事項 .PP 閱讀你係統中的 perl 自帶的 FAQ 和文檔 (例如,perlvms,perlplan9...)。它們會包含有關你的 perl 版本的更詳細的信息。 .Sh "如何找出正在運行的操作系統?" .IX Subsection "How do I find out which operating system I'm running under?"$^O 這個變數(若使用 English 模組就是 $OSTYPE)會指出你的 perl 解譯器執 行檔是替哪個作業系統、平臺所建的。 .Sh "爲什麼 exec() 不返回?" .IX Subsection "How come exec() doesn't return?" 因爲這正是它所做的:它用另一個不同的程式來取代你當時所執行的。如果你的程 式需要繼續跑下去(這可能正是你問此問題的原因吧?),改用 system() 。 .Sh "如何對鍵盤/螢幕/滑鼠做些花樣?" .IX Subsection "How do I do fancy stuff with the keyboard/screen/mouse?" 連接/控制 鍵盤、螢幕和指標裝置(「滑鼠」)的方法因作業系統的不同而有不 同;不妨試試下列模組: .IP "Keyboard" 4 .IX Item "Keyboard" .Vb 5 \& Term::Cap 標準內建模組 \& Term::ReadKey CPAN \& Term::ReadLine::Gnu CPAN \& Term::ReadLine::Perl CPAN \& Term::Screen CPAN .Ve .IP "Screen" 4 .IX Item "Screen" .Vb 3 \& Term::Cap 標準內建模組 \& Curses CPAN \& Term::ANSIColor CPAN .Ve .IP "Mouse" 4 .IX Item "Mouse" .Vb 1 \& Tk CPAN .Ve .PP Some of these specific cases are shown below. .Sh "How do I print something out in color?" .IX Subsection "How do I print something out in color?" In general, you don't, because you don't know whether the recipient has a color-aware display device. If you know that they have an \s-1ANSI\s0 terminal that understands color, you can use the Term::ANSIColor module from \s-1CPAN:\s0 .PP .Vb 3 \& use Term::ANSIColor; \& print color("red"), "Stop!\en", color("reset"); \& print color("green"), "Go!\en", color("reset"); .Ve .PP Or like this: .PP .Vb 3 \& use Term::ANSIColor qw(:constants); \& print RED, "Stop!\en", RESET; \& print GREEN, "Go!\en", RESET; .Ve .Sh "How do I read just one key without waiting for a return key?" .IX Subsection "How do I read just one key without waiting for a return key?" Controlling input buffering is a remarkably system-dependent matter. On many systems, you can just use the \fBstty\fR command as shown in \&\*(L"getc\*(R" in perlfunc, but as you see, that's already getting you into portability snags. .PP .Vb 6 \& open(TTY, "+/dev/tty 2>&1"; \& $key = getc(TTY); # perhaps this works \& # OR ELSE \& sysread(TTY, $key, 1); # probably this does \& system "stty -cbreak /dev/tty 2>&1"; .Ve .PP The Term::ReadKey module from \s-1CPAN\s0 offers an easy-to-use interface that should be more efficient than shelling out to \fBstty\fR for each key. It even includes limited support for Windows. .PP .Vb 4 \& use Term::ReadKey; \& ReadMode('cbreak'); \& $key = ReadKey(0); \& ReadMode('normal'); .Ve .PP However, using the code requires that you have a working C compiler and can use it to build and install a \s-1CPAN\s0 module. Here's a solution using the standard \s-1POSIX\s0 module, which is already on your systems (assuming your system supports \s-1POSIX\s0). .PP .Vb 2 \& use HotKey; \& $key = readkey(); .Ve .PP And here's the HotKey module, which hides the somewhat mystifying calls to manipulate the \s-1POSIX\s0 termios structures. .PP .Vb 2 \& # HotKey.pm \& package HotKey; .Ve .PP .Vb 2 \& @ISA = qw(Exporter); \& @EXPORT = qw(cbreak cooked readkey); .Ve .PP .Vb 3 \& use strict; \& use POSIX qw(:termios_h); \& my ($term, $oterm, $echo, $noecho, $fd_stdin); .Ve .PP .Vb 4 \& $fd_stdin = fileno(STDIN); \& $term = POSIX::Termios->new(); \& $term->getattr($fd_stdin); \& $oterm = $term->getlflag(); .Ve .PP .Vb 2 \& $echo = ECHO | ECHOK | ICANON; \& $noecho = $oterm & ~$echo; .Ve .PP .Vb 5 \& sub cbreak { \& $term->setlflag($noecho); # ok, so i don't want echo either \& $term->setcc(VTIME, 1); \& $term->setattr($fd_stdin, TCSANOW); \& } .Ve .PP .Vb 5 \& sub cooked { \& $term->setlflag($oterm); \& $term->setcc(VTIME, 0); \& $term->setattr($fd_stdin, TCSANOW); \& } .Ve .PP .Vb 7 \& sub readkey { \& my $key = ''; \& cbreak(); \& sysread(STDIN, $key, 1); \& cooked(); \& return $key; \& } .Ve .PP .Vb 1 \& END { cooked() } .Ve .PP .Vb 1 \& 1; .Ve .Sh "How do I check whether input is ready on the keyboard?" .IX Subsection "How do I check whether input is ready on the keyboard?" The easiest way to do this is to read a key in nonblocking mode with the Term::ReadKey module from \s-1CPAN\s0, passing it an argument of \-1 to indicate not to block: .PP .Vb 1 \& use Term::ReadKey; .Ve .PP .Vb 1 \& ReadMode('cbreak'); .Ve .PP .Vb 5 \& if (defined ($char = ReadKey(-1)) ) { \& # input was waiting and it was $char \& } else { \& # no input was waiting \& } .Ve .PP .Vb 1 \& ReadMode('normal'); # restore normal tty settings .Ve .Sh "How do I clear the screen?" .IX Subsection "How do I clear the screen?" If you only have do so infrequently, use \f(CW\*(C`system\*(C'\fR: .PP .Vb 1 \& system("clear"); .Ve .PP If you have to do this a lot, save the clear string so you can print it 100 times without calling a program 100 times: .PP .Vb 2 \& $clear_string = `clear`; \& print $clear_string; .Ve .PP If you're planning on doing other screen manipulations, like cursor positions, etc, you might wish to use Term::Cap module: .PP .Vb 3 \& use Term::Cap; \& $terminal = Term::Cap->Tgetent( {OSPEED => 9600} ); \& $clear_string = $terminal->Tputs('cl'); .Ve .Sh "How do I get the screen size?" .IX Subsection "How do I get the screen size?" If you have Term::ReadKey module installed from \s-1CPAN\s0, you can use it to fetch the width and height in characters and in pixels: .PP .Vb 2 \& use Term::ReadKey; \& ($wchar, $hchar, $wpixels, $hpixels) = GetTerminalSize(); .Ve .PP This is more portable than the raw \f(CW\*(C`ioctl\*(C'\fR, but not as illustrative: .PP .Vb 10 \& require 'sys/ioctl.ph'; \& die "no TIOCGWINSZ " unless defined &TIOCGWINSZ; \& open(TTY, "+autoflush(1); .Ve .Sp As mentioned in the previous item, this still doesn't work when using socket I/O between Unix and Macintosh. You'll need to hard code your line terminators, in that case. .IP "non-blocking input" 4 .IX Item "non-blocking input" 如果你正在做一個阻塞的 read() 或 sysread() 動作,則你需要安排一個鬧 鈴把手或提供一個逾時設定(參看 alarm)。如果你是用非阻擋式的 開檔,那麼就要配合非阻擋性的讀取,也就是說得用到4 個參數的 select() 來確 定此裝置的 輸出/入 是否已準備好了(參考 perlfunc 中的 select )。 .PP While trying to read from his caller-id box, the notorious Jamie Zawinski , after much gnashing of teeth and fighting with sysread, sysopen, \s-1POSIX\s0's tcgetattr business, and various other functions that go bump in the night, finally came up with this: .PP .Vb 13 \& sub open_modem { \& use IPC::Open2; \& my $stty = `/bin/stty -g`; \& open2( \e*MODEM_IN, \e*MODEM_OUT, "cu -l$modem_device -s2400 2>&1"); \& # starting cu hoses /dev/tty's stty settings, even when it has \& # been opened on a pipe... \& system("/bin/stty $stty"); \& $_ = ; \& chomp; \& if ( !m/^Connected/ ) { \& print STDERR "$0: cu printed `$_' instead of `Connected'\en"; \& } \& } .Ve .Sh "如何解碼加密的口令文件?" .IX Subsection "How do I decode encrypted password files?" 花大把大把的錢去買破解專用的硬體,這會讓你成爲焦點話題。 .PP 說正經的,如果是碰到 Unix 密碼檔的話就不行 - Unix 密碼系統用的是單向的加 密函數。像 Crack 之類的程式可以暴力地(並聰明地)試着猜出密碼,但無法 (也不能)保證速戰速決。 .PP 如果你耽心的是使用者選取不良的密碼,你應該在使用者換密碼時主動審覈(例如說修改 \fIpasswd\fR\|(1) 程式加入這個功能)。 .Sh "如何在後臺開啓進程?" .IX Subsection "How do I start a process in the background?" Several modules can start other processes that do not block your Perl program. You can use IPC::Open3, Parallel::Jobs, IPC::Run, and some of the \s-1POE\s0 modules. See \s-1CPAN\s0 for more details. .PP 你可以使用: .PP .Vb 1 \& system("cmd &") .Ve .PP 或是用 fork,像 perlfunc 中的 fork 裏寫的(在 perlipc 裏有更進一步的 範例)。如果你在 Unix 類的系統上的話,請注意以下幾件事情: .IP "\s-1STDIN\s0, \s-1STDOUT\s0, and \s-1STDERR\s0 are shared" 4 .IX Item "STDIN, STDOUT, 和 STDERR 是共享的" 主程序和背景程序(即「子」程序)共用同一個 STDIN、STDOUT 和 STDERR 檔案 把手。如果兩個程序想同時去讀、寫同一個檔案把手,就可能有怪事會發生。你也 許應該替子程序關閉或重新開啓這些把手。你可以用開啓一個管道 (pipe) 的方法 避免這些問題(參看 open)但是在某些系統上這樣做會強迫子程序 必須比父程序早死。 .IP "信號" 4 .IX Item "Signals" SIGCHLD、可能還有 SIGPIPE 這兩個訊號要抓到。當背景程序執行完成後就會送出 SIGCHLD 訊號。而當你寫入一個子程序已經關閉的檔案把手時就會收到 SIGPIPE 訊號(一個未抓住的 SIGPIPE 可能導致你的程式無聲無息地死去)。用 system("cmd&") 的話不會有這樣的問題。 .IP "殭屍進程" 4 .IX Item "Zombies" 你得做準備,在子程序結束時「收成」它: .Sp .Vb 1 \& $SIG{CHLD} = sub { wait }; .Ve .Sp .Vb 1 \& $SIG{CHLD} = 'IGNORE'; .Ve .Sp You can also use a double fork. You immediately \fIwait()\fR for your first child, and the init daemon will \fIwait()\fR for your grandchild once it exits. .Sp .Vb 8 \& unless ($pid = fork) { \& unless (fork) { \& exec "what you really wanna do"; \& die "exec failed!"; \& } \& exit 0; \& } \& waitpid($pid,0); .Ve .Sp 在 Signals 有範例程式教你怎麼做。用 system("prog &") 的 話不會有僵 程序的問題。 .Sh "如何截獲控制字符/信號?" .IX Subsection "How do I trap control characters/signals?" 你並不能真的 ``捕捉'' 一個控制字元。而是控制字元產生一個訊號讓你捕捉。關於訊號的資料可以在 Signals 以及駱駝書第六章裏找到。 .PP 要小心的是,大多 C 程式庫無法重新進入 [re-entrant]。因此當你要嘗試着在一 個處理器裏做 print() 動作,而這個處理器是由另一個stdio 的動作所叫出來的 話,你的內部結構可能會處於失調狀態,而程式可能會丟出記憶核心 (dump core)。 有的時候你可以用 syswrite() 取代 print() 以避免這個狀況。 .PP 除非你極爲小心,否則在一個訊號處理器中,唯一安全可做的是:設定一個變數後離開。而在第一個情況下,你在設定變數的時候應確定 malloc() 不會被叫出來 (譬如,設定一個已經有值的變數)。 .PP 例如: .PP .Vb 5 \& $Interrupted = 0; # 確定它有個值 \& $SIG{INT} = sub { \& $Interrupted++; \& syswrite(STDERR, "ouch\en", 5); \& } .Ve .PP 然而,因爲系統呼叫會自己重新啓動,你將會發現如果你用的是「慢的」呼叫,像 < FH>、read()、connect() 或 wait(),那麼將它們停下的唯一辦法是使 用「跳遠」的方式跳出來;也就是產生一個例外訊號。參看在 Signals 裏對阻擋性 flock() 的逾時處理器的說明,或駱駝書第六 章。 .Sh "在 Unix 系統中如何修改 shadow 文件?" .IX Subsection "How do I modify the shadow password file on a Unix system?" 如果你的 perl 安裝正確的話,在 perlfunc 裏描述的 getpw*() 函數應該就能夠讀取隱式密碼檔了(只有讀取權)。要更動該檔案內容,做一個新的密碼檔(這個檔案的格式因系統而異,請看 passwd(5) )然後用 pwd_mkdb(8)(參考 pwd_mkdb(5))來安裝新的密碼檔。 .Sh "如何設置時間和日期?" .IX Subsection "How do I set the time and date?" 假設你有足夠的權限,你應該可以用 date(1) 程式來設定系統的時間與日期。 (但沒有針對個別程序修改時間日期的方法)這機制在 Unix、MS-DOS、Windows 和 NT 下都能用;VMS 下則要用 set time 。 .PP 然而,如果你只是要更動你的時區,只消設定一個環境變數即可: .PP .Vb 3 \& $ENV{TZ} = "MST7MDT"; # unixish \& $ENV{'SYS$TIMEZONE_DIFFERENTIAL'}="-5" # vms \& system "trn comp.lang.perl.misc"; .Ve .Sh "如何 sleep() 或 alarm() 少於一秒的時間?" .IX Subsection "How can I sleep() or alarm() for under a second?" 如果你要比 sleep() 所提供的最小單位一秒更精細的話,最簡單的方法就是用 select 裏面寫的 select() 函數。試一試 Time::HiRes 和 BSD::Itimer 模塊 (可以從 CPAN 下載,從 Perl 5.8 開始 Time::HiRes 成爲標準發行的一部分). .Sh "如何測度少於一秒的時間?" .IX Subsection "How can I measure time under a second?" 一般來說,你可能做不到。 Time::HiRes 模組(CPAN 有,從 Perl 5.8 開始成爲標準發行的一部分)在某些系統上能達到此 功能。 .PP 總之,你可能做不到。但是如果你的 Perl 支援 syscall() 函數並支援類似 gettimeofday(2) 的系統呼叫,你也許可以這麼做: .PP .Vb 1 \& require 'sys/syscall.ph'; .Ve .PP .Vb 1 \& $TIMEVAL_T = "LL"; .Ve .PP .Vb 1 \& $done = $start = pack($TIMEVAL_T, ()); .Ve .PP .Vb 2 \& syscall(&SYS_gettimeofday, $start, 0) != -1 \& or die "gettimeofday: $!"; .Ve .PP .Vb 3 \& ########################## \& # DO YOUR OPERATION HERE # \& ########################## .Ve .PP .Vb 2 \& syscall( &SYS_gettimeofday, $done, 0) != -1 \& or die "gettimeofday: $!"; .Ve .PP .Vb 2 \& @start = unpack($TIMEVAL_T, $start); \& @done = unpack($TIMEVAL_T, $done); .Ve .PP .Vb 2 \& # fix microseconds \& for ($done[1], $start[1]) { $_ /= 1_000_000 } .Ve .PP .Vb 3 \& $delta_time = sprintf "%.4f", ($done[0] + $done[1] ) \& - \& ($start[0] + $start[1] ); .Ve .Sh "如何做 atexit()或 setjmp()/longjmp()的動作?(異常處理)" .IX Subsection "How can I do an atexit() or setjmp()/longjmp()? (Exception handling)" 第五版的 Perl 增加了 END 區塊,可以用來模擬 atexit()的效果。當程式或執行 緒(thread) 終了時就會去呼叫該包裝的 END 區塊(參考 perlmod 文件)。 .PP For example, you can use this to make sure your filter program managed to finish its output without filling up the disk: .PP .Vb 3 \& END { \& close(STDOUT) || die "stdout close failed: $!"; \& } .Ve .PP 如果當程式被沒有抓到的訊號終結了,END 區塊就不會被呼叫到,所以當你用 END 時應再加上 .PP .Vb 1 \& use sigtrap qw(die normal-signals); .Ve .PP Perl 的例外處理機制就是它的 eval() 運算子。你可以把 eval() 當做 setjmp 而die()當做 longjmp 來使用。更詳細的說明請參考 Signals 和 Camel書第六章裏關於訊號的那段,尤其是描述有關 flock() 的逾時處理器那段。 .PP 如果你只對例外處理的部分有興趣,試試 exceptions.pl 程式庫(包含在標準 perl裏)。 .PP 如果你要的是 atexit() 語法(以及 rmexit()),試試 CPAN 裏的 AtExit 模組。 .ie n .Sh "爲何我的 sockets程式在 System V (Solaris)系統下不能用?「不支持的協議」這個錯誤訊息又是什麼意思?" .el .Sh "爲何我的 sockets程式在 System V (Solaris)系統下不能用?「不支持的協議」這個錯誤訊息又是什麼意思?" .IX Subsection "Why doesn't my sockets program work under System V (Solaris)? What does the error message Protocol not supported mean?" 有些 Sys-V 根底的系統,特別像 Solaris 2.X,已重新將一些標準的 socket常數 定義過了。由於這些常數在各種架構下都是定值,所以在 perl程式碼中常被人寫 死在裏面。處理此問題的適當方式 是用 ``use Socket'' 來取得正確的值。 .PP 須注意儘管 SunOS 和 Solaris 在二進位執行檔上相容,這些值是相異的。自己去 想爲什麼吧。 .Sh "如何從 Perl裏呼叫系統中獨特的 C函數?" .IX Subsection "How can I call my system's unique C functions from Perl?" 通常是寫個外部的模組來處理 - 參看「我要如何學到將 C 與 Perl 連結在一起? [h2xs, xsubpp]」 這問題的答案。然而,如果此函數是個系統呼叫,而你的系統 有支援 syscall(),那麼可以用 syscall 函數(說明在 perlfunc 裏)。 .PP 切記先查查看你的 perl 版本中所附的模組以及 CPAN 裏的模組,因爲也許某人已 經寫了個這樣的模組。 On Windows, try Win32::API. On Macs, try Mac::Carbon. If no module has an interface to the C function, you can inline a bit of C in your Perl source with Inline::C. .Sh "在哪裏可以找引入檔來做 ioctl()或 syscall()?" .IX Subsection "Where do I get the include files to do ioctl() or syscall()?" 以前這些檔案會由標準 perl 發行中所附的 h2ph 工具來產生。這個程式將 C 標 頭檔案裏的 cpp(1)指令轉換成內含副程式定義的檔案,像 &SYS_getitimer,你可 以把它當做函數的參數。這樣做並不怎麼完美,但通常可達成任務。簡單的像 errno.h 、syscall.h 和socket.h 這些檔案都沒問題,但像 ioctl.h 這種較難的檔案總是需要人工編輯。以下是安裝 *.ph 檔案的步驟: .PP .Vb 3 \& 1. 成爲超級用戶 \& 2. cd /usr/include \& 3. h2ph *.h */*.h .Ve .PP 如果你的系統支援動態載入,那麼爲了可移植性、而且合理的做法是使用 h2xs(也 是 perl的標準配備)。這個工具將 C 標頭檔案轉換成 Perl 的衍伸檔案 (extensions)。 h2xs 的入門要看 perlxstut 。 .PP 如果你的系統不支援動態載入,你可能仍應使用 h2xs。參看 perlxstut 和 MakeMaker (簡單來說,就是用 make perl 、而非 make 來重 建一份使用新的靜態連結的 perl)。 .Sh "爲何 setuid perl程式會抱怨關於系統核心的問題?" .IX Subsection "Why do setuid perl scripts complain about kernel problems?" 有些作業系統的核心有臭蟲使得 setuid 程式在先天上就不安全。Perl提供你一些方法(在 perlsec 裏有寫)可跳過這些系統的缺陷。 .Sh "如何打開對某程式既輸入又輸出的管道 (pipe)?" .IX Subsection "How can I open a pipe both to and from a command?" IPC::Open2 模組(perl 的標準配件)是個好用的方法,它在內部是藉着pipe()、 fork() 和 exec() 來完成此工作。不過切記要讀它文件裏關於鎖死的警告 ( 參見 IPC::Open2 )。參見 perlipc 中的 \*(L"Bidirectional Communication with Another Process\*(R" 和 \&\*(L"Bidirectional Communication with Yourself\*(R" .PP You may also use the IPC::Open3 module (part of the standard perl distribution), but be warned that it has a different order of arguments from IPC::Open2 (see IPC::Open3). .Sh "爲何用 system()卻得不到一個指令的輸出呢?" .IX Subsection "Why can't I get the output of a command with system()?" 你把 system() 和反向引號 (``) 的用法搞混了。 system() 會執行一個指令然後 傳回指令結束時的狀況資訊(以一個 16 進位值表示:低位元是程序中止所收到的 訊號,高位元纔是真正離開時的傳回值)。反向引號 (``) 執行一個指令並且把它 所送出的東西送到 STDOUT。 .PP .Vb 2 \& $exit_status = system("mail-users"); \& $output_string = `ls`; .Ve .Sh "如何捕捉外部指令的 STDERR?" .IX Subsection "How can I capture STDERR from an external command?" 有叄種基本方式執行外部指令: .PP .Vb 3 \& system $cmd; # 使用 system() \& $output = `$cmd`; # 使用 backticks (``) \& open (PIPE, "cmd |"); # 使用 open() .Ve .PP 在 system() 下,STDOUT 和 STDERR 都會輸出到和 script 本身的 STDOUT, STDERR相同的出處,除非指令本身將它們導向它處。反向引號和 open() 則 只 讀取指令的 STDOUT 部份。 .PP 你也可以使用 IPC::Open3 模組. Benjamin Goldberg provides some sample code: .PP To capture a program's \s-1STDOUT\s0, but discard its \s-1STDERR:\s0 .PP .Vb 7 \& use IPC::Open3; \& use File::Spec; \& use Symbol qw(gensym); \& open(NULL, ">", File::Spec->devnull); \& my $pid = open3(gensym, \e*PH, ">&NULL", "cmd"); \& while( ) { } \& waitpid($pid, 0); .Ve .PP To capture a program's \s-1STDERR\s0, but discard its \s-1STDOUT:\s0 .PP .Vb 7 \& use IPC::Open3; \& use File::Spec; \& use Symbol qw(gensym); \& open(NULL, ">", File::Spec->devnull); \& my $pid = open3(gensym, ">&NULL", \e*PH, "cmd"); \& while( ) { } \& waitpid($pid, 0); .Ve .PP To capture a program's \s-1STDERR\s0, and let its \s-1STDOUT\s0 go to our own \s-1STDERR:\s0 .PP .Vb 5 \& use IPC::Open3; \& use Symbol qw(gensym); \& my $pid = open3(gensym, ">&STDERR", \e*PH, "cmd"); \& while( ) { } \& waitpid($pid, 0); .Ve .PP To read both a command's \s-1STDOUT\s0 and its \s-1STDERR\s0 separately, you can redirect them to temp files, let the command run, then read the temp files: .PP .Vb 10 \& use IPC::Open3; \& use Symbol qw(gensym); \& use IO::File; \& local *CATCHOUT = IO::File->new_tempfile; \& local *CATCHERR = IO::File->new_tempfile; \& my $pid = open3(gensym, ">&CATCHOUT", ">&CATCHERR", "cmd"); \& waitpid($pid, 0); \& seek $_, 0, 0 for \e*CATCHOUT, \e*CATCHERR; \& while( ) {} \& while( ) {} .Ve .PP But there's no real need for *both* to be tempfiles... the following should work just as well, without deadlocking: .PP .Vb 9 \& use IPC::Open3; \& use Symbol qw(gensym); \& use IO::File; \& local *CATCHERR = IO::File->new_tempfile; \& my $pid = open3(gensym, \e*CATCHOUT, ">&CATCHERR", "cmd"); \& while( ) {} \& waitpid($pid, 0); \& seek CATCHERR, 0, 0; \& while( ) {} .Ve .PP And it'll be faster, too, since we can begin processing the program's stdout immediately, rather than waiting for the program to finish. .PP 在上述方法中,你可以在呼叫前更改文件描述符 (file descriptor) 名稱: .PP .Vb 2 \& open(STDOUT, ">logfile"); \& system("ls"); .Ve .PP 或者使用 Bourne shell 的文件描述符重導功能: .PP .Vb 2 \& $output = `$cmd 2>some_file`; \& open (PIPE, "cmd 2>some_file |"); .Ve .PP 也可以用檔案描述元重導功能將 STDERR 複製爲 STDOUT: .PP .Vb 2 \& $output = `$cmd 2>&1`; \& open (PIPE, "cmd 2>&1 |"); .Ve .PP 注意你 不能 光是將 STDERR 開成 STDOUT 的複製,而不呼叫 shell來做這個 重導的工作。這樣是不行的: .PP .Vb 2 \& open(STDERR, ">&STDOUT"); \& $alloutput = `cmd args`; # stderr still escapes .Ve .PP 失敗的原因是,open() 讓 STDERR 在呼叫 open() 時往 STDOUT的方向走。然後反 向引號讓 STDOUT的內容跑到一個字串變數裏,但是沒有改變 STDERR 的去向(它 仍然往舊的 STDOUT那裏跑)。 .PP 注意,在反向引號裏你 必須 使用 Bourne shell (sh(1)) 重導的語法而非 csh(1)的!至於爲何 Perl 的 system()、反向引號和開管道都用 Bourne shell語法的原因,可在下址找到:\*(L"Far More Than You Ever Wanted To Know\*(R", http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz . 要同時捕捉一個命令的 \s-1STDERR\s0 和 \s-1STDOUT\s0: .PP .Vb 3 \& $output = `cmd 2>&1`; # either with backticks \& $pid = open(PH, "cmd 2>&1 |"); # or with an open pipe \& while () { } # plus a read .Ve .PP To capture a command's \s-1STDOUT\s0 but discard its \s-1STDERR:\s0 .PP .Vb 3 \& $output = `cmd 2>/dev/null`; # either with backticks \& $pid = open(PH, "cmd 2>/dev/null |"); # or with an open pipe \& while () { } # plus a read .Ve .PP To capture a command's \s-1STDERR\s0 but discard its \s-1STDOUT:\s0 .PP .Vb 3 \& $output = `cmd 2>&1 1>/dev/null`; # either with backticks \& $pid = open(PH, "cmd 2>&1 1>/dev/null |"); # or with an open pipe \& while () { } # plus a read .Ve .PP To exchange a command's \s-1STDOUT\s0 and \s-1STDERR\s0 in order to capture the \s-1STDERR\s0 but leave its \s-1STDOUT\s0 to come out our old \s-1STDERR:\s0 .PP .Vb 3 \& $output = `cmd 3>&1 1>&2 2>&3 3>&-`; # either with backticks \& $pid = open(PH, "cmd 3>&1 1>&2 2>&3 3>&-|");# or with an open pipe \& while () { } # plus a read .Ve .PP To read both a command's \s-1STDOUT\s0 and its \s-1STDERR\s0 separately, it's easiest and safest to redirect them separately to files, and then read from those files when the program is done: .PP .Vb 1 \& system("program args 1>/tmp/program.stdout 2>/tmp/program.stderr"); .Ve .PP Ordering is important in all these examples. That's because the shell processes file descriptor redirections in strictly left to right order. .PP .Vb 2 \& system("prog args 1>tmpfile 2>&1"); \& system("prog args 2>&1 1>tmpfile"); .Ve .PP The first command sends both standard out and standard error to the temporary file. The second command sends only the old standard output there, and the old standard error shows up on the old standard out. .Sh "爲何當管道開啓失敗時 open()不會傳回錯誤訊息?" .IX Subsection "Why doesn't open() return an error when a pipe open fails?" If the second argument to a piped \fIopen()\fR contains shell metacharacters, perl \fIfork()\fRs, then \fIexec()\fRs a shell to decode the metacharacters and eventually run the desired program. If the program couldn't be run, it's the shell that gets the message, not Perl. All your Perl program can find out is whether the shell itself could be successfully started. You can still capture the shell's \s-1STDERR\s0 and check it for error messages. See \*(L"How can I capture \s-1STDERR\s0 from an external command?\*(R" elsewhere in this document, or use the IPC::Open3 module. .PP If there are no shell metacharacters in the argument of \fIopen()\fR, Perl runs the command directly, without using the shell, and can correctly report whether the command started. .Sh "在忽略返回值的上下文裏使用反向引號有何不對?" .IX Subsection "What's wrong with using backticks in a void context?" 嚴格說起來,沒啥不對。但從程式寫作嚴謹與否來說,這樣無法寫出較易維護的程式碼。Perl 有多種方法可以運行外部命令。反引號只是其中一個;它收集命令的輸出,在程序中加以應用。 \f(CW\*(C`system\*(C'\fR 函數是另一個,它不這樣做 .PP Writing backticks in your program sends a clear message to the readers of your code that you wanted to collect the output of the command. Why send a clear message that isn't true? .PP 再看看下列這一行: .PP .Vb 1 \& `cat /etc/termcap`; .Ve .PP 你還沒有指定輸出,所以它會浪費記憶體(就那麼一下子)。另外你也忘了檢查 \f(CW$?\fR 看看程式是否正確的執行。即使你寫成 .PP .Vb 1 \& print `cat /etc/termcap`; .Ve .PP 但在大部份情況下,這本來可以、而且也應該寫成 .PP .Vb 2 \& system("cat /etc/termcap") == 0 \& or die "cat program failed!"; .Ve .PP 這樣可快速地得到輸出(一產生出來就會得到,不用等到最後),並且檢查傳回值。 .PP \&\fIsystem()\fR 同時具有直接決定是否先做 shell 萬用字元 (wildcard)處理的功能, 反向引號就不行。 .Sh "如何不經過 shell處理來呼叫反向引號?" .IX Subsection "How can I call backticks without shell processing?" 這需要些技巧。不能寫成這樣: .PP .Vb 1 \& @ok = `grep @opts '$search_string' @filenames`; .Ve .PP 在 Perl 5.8.0 中,你可以使用有多個參數的 \fIopen()\fR。類似 \fIsystem()\fR 和 \fIexec()\fR 的列表形式,不會進行 shell 轉義。 .PP .Vb 3 \& open( GREP, "-|", 'grep', @opts, $search_string, @filenames ); \& chomp(@ok = ); \& close GREP; .Ve .PP 也可以這樣: .PP .Vb 10 \& my @ok = (); \& if (open(GREP, "-|")) { \& while () { \& chomp; \& push(@ok, $_); \& } \& close GREP; \& } else { \& exec 'grep', @opts, $search_string, @filenames; \& } .Ve .PP 一如 system(),當你 exec() 一個序列時不會有 shell 解譯的情況發生。更多示例可以從 perlipc 的 \*(L"Safe Pipe Opens\*(R" 中找到。 .PP Note that if you're use Microsoft, no solution to this vexing issue is even possible. Even if Perl were to emulate \fIfork()\fR, you'd still be stuck, because Microsoft does not have a argc/argv\-style \s-1API\s0. .Sh "爲何給了 EOF(Unix上是 ^D,MS-DOS上是 ^Z)後我的程式就不能從 STDIN 讀取東西了呢?" .IX Subsection "Why can't my script read from STDIN after I gave it EOF (^D on Unix, ^Z on MS-DOS)?" 因爲某些 stdio 的 set error 和 eof 旗標需要清除。你可以用 POSIX 模組裏定 義的clearerr()。這是在技術上正確的解決之道。還有一些較不保險的方法: .IP "1" 4 .IX Item "1" 試着保存搜尋指標然後去找它,例如: .Sp .Vb 2 \& $where = tell(LOG); \& seek(LOG, $where, 0); .Ve .IP "2" 4 .IX Item "2" 如果那樣行不通,試着去 seek() 檔案的另一部份然後再找回來。 .IP "3" 4 .IX Item "3" 如果還是行不通,試着 seek() 檔案另一個相異的的部份,讀點東西,再回去找。 .IP "4" 4 .IX Item "4" 如果依然不行,放棄使用 stdio 改用 sysread。 .Sh "如何把 shell程式轉成 perl?" .IX Subsection "How can I convert my shell script to perl?" 學習 Perl 然後重寫。說真的,沒有簡單的轉換方式。用 shell 做起來很笨的工 作可以用 Perl 很輕鬆的做到,而就是這些麻煩之處使得 shell->perl 轉換程式 非常不可能寫得出來。在重新撰寫程式的過程裏,你會認清自己真正要做的工作爲 何,也希望能夠跳脫 shell 的管線資料流機制 [pipeline datastream paradigm], 這東西雖對某些事情很方便,但也常造成低效率。 .Sh "perl能處理 telnet或 ftp 會話嗎?" .IX Subsection "Can I use perl to run a telnet or ftp session?" 試試 Net::FTP、TCP::Client 和 NET::Telnet 模組(CPAN 有)。 http://www.perl.com/CPAN/scripts/netstuff/telnet.emul.shar 也有助於模擬 telnet 協定,但是 Net::Telnet 可能較容易使用。 .PP 如果你所要做的只是假裝 telnet 但又不要起始 telnet 時的溝通程序,那麼以下這個標準的雙程序方式就可以滿足你的需要了: .PP .Vb 12 \& use IO::Socket; # new in 5.004 \& $handle = IO::Socket::INET->new('www.perl.com:80') \& || die "can't connect to port 80 on www.perl.com: $!"; \& $handle->autoflush(1); \& if (fork()) { # XXX: undef means failure \& select($handle); \& print while ; # everything from stdin to socket \& } else { \& print while <$handle>; # everything from socket to stdout \& } \& close $handle; \& exit; .Ve .Sh "如何在 Perl裏達到 Expect的功能?" .IX Subsection "How can I write expect in Perl?" 很久很久以前,有個叫做 chat2.pl 的程式庫(perl 標準配備之一),但一直沒 真正完工。如果遇到它的話,不要去用它。現在,你的最佳選擇就是從 CPAN 來的 Expect 模塊,同時它需要 CPAN 的另兩個模塊, IO::Pty 和 IO::Stty. .ie n .Sh "有沒有可能將 perl的指令列隱藏起來,以躲避像 "ps"之類的程式?" .el .Sh "有沒有可能將 perl的指令列隱藏起來,以躲避像 ``ps''之類的程式?" .IX Subsection "Is there a way to hide perl's command line from programs such as ps?" 首先要注意的是,如果你的目的是爲了安全(例如避免人們偷看到密碼),那你應該重寫你的程式,把重要的資訊從參數中剔除。光是隱藏起來不會讓你的程式變得完全安全。 .PP 如要真的把看得見的指令列改掉,你可以設定 $0 這個變數值,如同 perlvar 裏寫的。但這方法並非各種作業系統都適用。像 sendmail之類的背景程式 (daemons) 就將它們的狀態放在那兒: .PP .Vb 1 \& $0 = "orcus [accepting connections]"; .Ve .Sh "我在 perl script裏 {更動目錄,更改我的使用環境}。爲何這些改變在程式執行完後就消失了呢?如何讓我做的修改顯露出來?" .IX Subsection "I {changed directory, modified my environment} in a perl script. How come the change disappeared when I exited the script? How do I get my changes to be visible?" .IP "Unix" 4 .IX Item "Unix" 嚴格的說起來,這是做不到的-一個 script 的執行是從啓動它的 shell 生出一 個不同的程序來執行。這個程序的任何變動不會反映到它的父程序,只會反映到更 改之後它自己創造出來的子程序。有個 shell 魔術可以讓你藉着在 shell 裏 eval()你 script 的輸出來裝出這種效果,在 comp.unix.questions FAQ 裏有詳 細內容。 .Sh "如何關閉一個程序的文件句柄而不用等它完成呢?" .IX Subsection "How do I close a process's filehandle without waiting for it to complete?" 假設你的系統支援這種功能,那就只要送個適當的訊號給此程序(參看 kill)。通常是先送一個 TERM 訊號,等一下下,然後再送個 KILL 訊號去終結它。 .Sh "如何 fork 一個守護進程?" .IX Subsection "How do I fork a daemon process?" 如果你所指的是離線的程序(未與 tty 連線者),那下列的程序據說在大部份的 Unix系統都能用。非 Unix 系統的使用者應該檢查 Your_OS::Process 模組看看有 沒有其他的解決方案。 .IP "\(bu" 4 打開 /dev/tty 然後對它用 TIOCNOTTY ioctl。請參考 tty(4) 。更好的辦法,你可以只用 \fIPOSIX::setsid()\fR 函數,從而不必擔心進程組。 .IP "\(bu" 4 把目錄換到 / .IP "\(bu" 4 重開 STDIN、STDOUT 和 STDERR 使它們不會與舊的 tty 連接。 .IP "\(bu" 4 用下列方法把程式丟到後臺: .Sp .Vb 1 \& fork && exit; .Ve .PP The Proc::Daemon module, available from \s-1CPAN\s0, provides a function to perform these actions for you. .Sh "如何知道自己是否在交互地運行?" .IX Subsection "How do I find out if I'm running interactively or not?" 問得好。有的時候 \f(CW\*(C`\-t STDIN\*(C'\fRN 和 \f(CW\*(C`\-t STDOUT\*(C'\fR 可以提供線索,有時不行。 .PP .Vb 3 \& if (-t STDIN && -t STDOUT) { \& print "Now what? "; \& } .Ve .PP 在 POSIX 系統中,你可以用以下方法測試你自己的程序羣組與現在控制你終端機 的是否相同: .PP .Vb 9 \& use POSIX qw/getpgrp tcgetpgrp/; \& open(TTY, "/dev/tty") or die $!; \& $tpgrp = tcgetpgrp(fileno(*TTY)); \& $pgrp = getpgrp(); \& if ($tpgrp == $pgrp) { \& print "foreground\en"; \& } else { \& print "background\en"; \& } .Ve .Sh "如何爲緩慢的事件設置超時?" .IX Subsection "How do I timeout a slow event?" 如同 Signals 和 Camel 書第六章裏所描述的,用 alarm() 函數, 或許再配合上一個訊號處理器。你也可以改用 CPAN 裏更具彈性的 Sys::AlarmCall 模組來做。 .PP The \fIalarm()\fR function is not implemented on all versions of Windows. Check the documentation for your specific version of Perl. .Sh "如何設置 CPU 限額?" .IX Subsection "How do I set CPU limits?" 使用 CPAN 裏的 BSD::Resource 模組。 .Sh "如何避免在 Unix 系統中產生殭屍進程?" .IX Subsection "How do I avoid zombies on a Unix system?" 使用 Signals 裏面叫 reaper 的程式碼,在接到 SIGCHLD 時會呼 叫wait(),或是用 perlfaq8 中的 \*(L"How do I start a process in the background?\*(R" 裏面寫的雙 fork 技巧。 .Sh "如何使用 SQL 數據庫?" .IX Subsection "How do I use an SQL database?" The \s-1DBI\s0 module provides an abstract interface to most database servers and types, including Oracle, \s-1DB2\s0, Sybase, mysql, Postgresql, \&\s-1ODBC\s0, and flat files. The \s-1DBI\s0 module accesses each database type through a database driver, or \s-1DBD\s0. You can see a complete list of available drivers on \s-1CPAN:\s0 http://www.cpan.org/modules/by\-module/DBD/ . You can read more about \s-1DBI\s0 on http://dbi.perl.org . .PP Other modules provide more specific access: Win32::ODBC, Alzabo, iodbc, and others found on \s-1CPAN\s0 Search: http://search.cpan.org . .Sh "如何使 system() 在收到 control-C 時退出?" .IX Subsection "How do I make a system() exit on control-C?" 做不到。你需要摹仿 system() 呼叫(參看 perlipc 裏的範例程式),然後設計一個訊號處理器,讓它把 INT 訊號傳給子程序。或者可以檢測它: .PP .Vb 2 \& $rc = system($cmd); \& if ($rc & 127) { die "signal death" } .Ve .Sh "如何無阻塞地打開一個文件?" .IX Subsection "How do I open a file without blocking?" 如果你有幸使用到支援無阻塞讀的系統(大部份 Unix 般的系統都有支援), 你只需要用 Fcntl 模組裏的 O_NDELAY 或 O_NONBLOCK 旗標,配合 sysopen(): .PP .Vb 3 \& use Fcntl; \& sysopen(FH, "/tmp/somefile", O_WRONLY|O_NDELAY|O_CREAT, 0644) \& or die "can't open /tmp/somefile: $!": .Ve .Sh "How do I install a module from \s-1CPAN\s0?" .IX Subsection "如何從 CPAN 安裝模塊?" 最簡單的方法就是讓 CPAN 這個模組替你代勞。這個模組包含在 5.004及以後的版 本中。 .PP .Vb 1 \& $ perl -MCPAN -e shell .Ve .PP .Vb 2 \& cpan shell -- CPAN exploration and modules installation (v1.59_54) \& ReadLine support enabled .Ve .PP .Vb 1 \& cpan> install Some::Module .Ve .PP 如要手動安裝 CPAN 模組,或是任何按規矩發展的 CPAN模組,遵循以下步 驟: .IP "1" 4 .IX Item "1" 把源代碼解壓到臨時目錄 .IP "2" 4 .IX Item "2" .Vb 1 \& perl Makefile.PL .Ve .IP "3" 4 .IX Item "3" .Vb 1 \& make .Ve .IP "4" 4 .IX Item "4" .Vb 1 \& make test .Ve .IP "5" 4 .IX Item "5" .Vb 1 \& make install .Ve .PP 如果你用的 perl 版本在編譯時沒有建入動態連結的功能,那你只消把第叄步 (make)換成 make perl 然後你就會得到一個新的 perl 執行檔,裏頭連 有你新加入的延伸。 .PP 在 ExtUtils::MakeMaker 裏面有更多關於建構模組的細節,並參考下一個問題,require 和 use 的區別是什麼?。 .Sh "require 和 use 的區別是什麼?" .IX Subsection "What's the difference between require and use?" Perl offers several different ways to include code from one file into another. Here are the deltas between the various inclusion constructs: .PP .Vb 3 \& 1) do $file is like eval `cat $file`, except the former \& 1.1: searches @INC and updates %INC. \& 1.2: bequeaths an *unrelated* lexical scope on the eval'ed code. .Ve .PP .Vb 3 \& 2) require $file is like do $file, except the former \& 2.1: checks for redundant loading, skipping already loaded files. \& 2.2: raises an exception on failure to find, compile, or execute $file. .Ve .PP .Vb 3 \& 3) require Module is like require "Module.pm", except the former \& 3.1: translates each "::" into your system's directory separator. \& 3.2: primes the parser to disambiguate class Module as an indirect object. .Ve .PP .Vb 3 \& 4) use Module is like require Module, except the former \& 4.1: loads the module at compile time, not run-time. \& 4.2: imports symbols and semantics from that package to the current one. .Ve .PP In general, you usually want \f(CW\*(C`use\*(C'\fR and a proper Perl module. .Sh "如何設置我自己的模塊/庫路徑?" .IX Subsection "How do I keep my own module/library directory?" 當你建構模組時,在產生 Makefiles 時使用 PREFIX 選項: .PP .Vb 1 \& perl Makefile.PL PREFIX=/mydir/perl LIB=/mydir/perl/lib .Ve .PP 然後在執行用到此 模組/程式庫 的程式前先設好 PERL5LIB 環境變數(參考 perlrun ),或是用 .PP .Vb 1 \& use lib '/mydir/perl/lib'; .Ve .PP 這樣與下面幾乎相同 .PP .Vb 3 \& BEGIN { \& unshift(@INC, '/mydir/perl/lib'); \& } .Ve .PP 但 lib 模塊檢測獨立於機器的子目錄。參見 Perl 的 lib 模塊來獲取詳細信息。 .Sh "如何將我自己的程序的路徑加入到模塊/庫搜索路徑中?" .IX Subsection "How do I add the directory my program lives in to the module/library search path?" .Vb 3 \& use FindBin; \& use lib "$FindBin::Bin"; \& use your_own_modules; .Ve .Sh "如何在運行時將一個目錄加入到我的 include 路徑 (@INC) 中?" .IX Subsection "How do I add a directory to my include path (@INC) at runtime?" 以下是我們建議更動引入路徑的方法: .PP .Vb 5 \& 環境變量 PERLLIB \& 環境變量 PERL5LIB \& perl -Idir 命令行標誌 \& use lib 編用,類似 \& use lib "$ENV{HOME}/myown_perllib"; .Ve .PP 後者特別有用,因爲它知道與機器相關的架構。lib.pm 機制模組是從 5.002 版開 始包含在 Perl 裏面的。 .Sh "什麼是 socket.ph,從哪兒可以得到它?" .IX Subsection "What is socket.ph and where do I get it?" It's a perl4\-style file defining values for system networking constants. Sometimes it is built using h2ph when Perl is installed, but other times it is not. Modern programs \f(CW\*(C`use Socket;\*(C'\fR instead. .SH "AUTHOR AND COPYRIGHT" .IX Header "AUTHOR AND COPYRIGHT" Copyright (c) 1997\-2003 Tom Christiansen and Nathan Torkington. All rights reserved. .PP This documentation is free; you can redistribute it and/or modify it under the same terms as Perl itself. .PP Irrespective of its distribution, all code examples in this file are hereby placed into the public domain. You are permitted and encouraged to use this code in your own programs for fun or for profit as you see fit. A simple comment in the code giving credit would be courteous but is not required. .SH "譯者" .B 陳彥銘,蕭百齡,兩隻老虎工作室 .Sh "跋" .br 本頁面中文版由中文 man 手冊頁計劃提供。 .br 中文 man 手冊頁計劃:\fBhttps://github.com/man-pages-zh/manpages-zh\fR