📄 perlfaq8.1
字号:
\&\& ReadMode(\*(Aqnoecho\*(Aq);\& $password = ReadLine(0);.Ve.Sh "How do I read and write the serial port?".IX Subsection "How do I read and write the serial port?"This depends on which operating system your program is running on. Inthe case of Unix, the serial ports will be accessible through files in/dev; on other systems, device names will doubtless differ.Several problem areas common to all device interaction are thefollowing:.IP "lockfiles" 4.IX Item "lockfiles"Your system may use lockfiles to control multiple access. Make sureyou follow the correct protocol. Unpredictable behavior can resultfrom multiple processes reading from one device..IP "open mode" 4.IX Item "open mode"If you expect to use both read and write operations on the device,you'll have to open it for update (see \*(L"open\*(R" in perlfunc fordetails). You may wish to open it without running the risk ofblocking by using \fIsysopen()\fR and \f(CW\*(C`O_RDWR|O_NDELAY|O_NOCTTY\*(C'\fR from theFcntl module (part of the standard perl distribution). See\&\*(L"sysopen\*(R" in perlfunc for more on this approach..IP "end of line" 4.IX Item "end of line"Some devices will be expecting a \*(L"\er\*(R" at the end of each line ratherthan a \*(L"\en\*(R". In some ports of perl, \*(L"\er\*(R" and \*(L"\en\*(R" are different fromtheir usual (Unix) \s-1ASCII\s0 values of \*(L"\e012\*(R" and \*(L"\e015\*(R". You may have togive the numeric values you want directly, using octal (\*(L"\e015\*(R"), hex(\*(L"0x0D\*(R"), or as a control-character specification (\*(L"\ecM\*(R")..Sp.Vb 2\& print DEV "atv1\e012"; # wrong, for some devices\& print DEV "atv1\e015"; # right, for some devices.Ve.SpEven though with normal text files a \*(L"\en\*(R" will do the trick, there isstill no unified scheme for terminating a line that is portablebetween Unix, DOS/Win, and Macintosh, except to terminate \fI\s-1ALL\s0\fR lineends with \*(L"\e015\e012\*(R", and strip what you don't need from the output.This applies especially to socket I/O and autoflushing, discussednext..IP "flushing output" 4.IX Item "flushing output"If you expect characters to get to your device when you \fIprint()\fR them,you'll want to autoflush that filehandle. You can use \fIselect()\fRand the \f(CW$|\fR variable to control autoflushing (see \*(L"$|\*(R" in perlvarand \*(L"select\*(R" in perlfunc, or perlfaq5, \*(L"How do I flush/unbuffer anoutput filehandle? Why must I do this?\*(R"):.Sp.Vb 3\& $oldh = select(DEV);\& $| = 1;\& select($oldh);.Ve.SpYou'll also see code that does this without a temporary variable, as in.Sp.Vb 1\& select((select(DEV), $| = 1)[0]);.Ve.SpOr if you don't mind pulling in a few thousand linesof code just because you're afraid of a little $| variable:.Sp.Vb 2\& use IO::Handle;\& DEV\->autoflush(1);.Ve.SpAs mentioned in the previous item, this still doesn't work when usingsocket I/O between Unix and Macintosh. You'll need to hard code yourline terminators, in that case..IP "non-blocking input" 4.IX Item "non-blocking input"If you are doing a blocking \fIread()\fR or \fIsysread()\fR, you'll have toarrange for an alarm handler to provide a timeout (see\&\*(L"alarm\*(R" in perlfunc). If you have a non-blocking open, you'll likelyhave a non-blocking read, which means you may have to use a 4\-arg\&\fIselect()\fR to determine whether I/O is ready on that device (see\&\*(L"select\*(R" in perlfunc..PPWhile trying to read from his caller-id box, the notorious Jamie Zawinski\&\f(CW\*(C`<jwz@netscape.com>\*(C'\fR, after much gnashing of teeth and fighting with sysread,sysopen, \s-1POSIX\s0's tcgetattr business, and various other functions thatgo bump in the night, finally came up with this:.PP.Vb 10\& 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\*(Aqs stty settings, even when it has\& # been opened on a pipe...\& system("/bin/stty $stty");\& $_ = <MODEM_IN>;\& chomp;\& if ( !m/^Connected/ ) {\& print STDERR "$0: cu printed \`$_\*(Aq instead of \`Connected\*(Aq\en";\& }\& }.Ve.Sh "How do I decode encrypted password files?".IX Subsection "How do I decode encrypted password files?"You spend lots and lots of money on dedicated hardware, but this isbound to get you talked about..PPSeriously, you can't if they are Unix password files\*(--the Unixpassword system employs one-way encryption. It's more like hashingthan encryption. The best you can do is check whether something elsehashes to the same string. You can't turn a hash back into theoriginal string. Programs like Crack can forcibly (and intelligently)try to guess passwords, but don't (can't) guarantee quick success..PPIf you're worried about users selecting bad passwords, you shouldproactively check when they try to change their password (by modifying\&\fIpasswd\fR\|(1), for example)..Sh "How do I start a process in the background?".IX Subsection "How do I start a process in the background?"Several modules can start other processes that do not blockyour Perl program. You can use IPC::Open3, Parallel::Jobs,IPC::Run, and some of the \s-1POE\s0 modules. See \s-1CPAN\s0 for moredetails..PPYou could also use.PP.Vb 1\& system("cmd &").Ve.PPor you could use fork as documented in \*(L"fork\*(R" in perlfunc, withfurther examples in perlipc. Some things to be aware of, if you'reon a Unix-like system:.IP "\s-1STDIN\s0, \s-1STDOUT\s0, and \s-1STDERR\s0 are shared" 4.IX Item "STDIN, STDOUT, and STDERR are shared"Both the main process and the backgrounded one (the \*(L"child\*(R" process)share the same \s-1STDIN\s0, \s-1STDOUT\s0 and \s-1STDERR\s0 filehandles. If both try toaccess them at once, strange things can happen. You may want to closeor reopen these for the child. You can get around this with\&\f(CW\*(C`open\*(C'\fRing a pipe (see \*(L"open\*(R" in perlfunc) but on some systems thismeans that the child process cannot outlive the parent..IP "Signals" 4.IX Item "Signals"You'll have to catch the \s-1SIGCHLD\s0 signal, and possibly \s-1SIGPIPE\s0 too.\&\s-1SIGCHLD\s0 is sent when the backgrounded process finishes. \s-1SIGPIPE\s0 issent when you write to a filehandle whose child process has closed (anuntrapped \s-1SIGPIPE\s0 can cause your program to silently die). This isnot an issue with \f(CW\*(C`system("cmd&")\*(C'\fR..IP "Zombies" 4.IX Item "Zombies"You have to be prepared to \*(L"reap\*(R" the child process when it finishes..Sp.Vb 1\& $SIG{CHLD} = sub { wait };\&\& $SIG{CHLD} = \*(AqIGNORE\*(Aq;.Ve.SpYou can also use a double fork. You immediately \fIwait()\fR for yourfirst child, and the init daemon will \fIwait()\fR for your grandchild onceit exits..Sp.Vb 8\& unless ($pid = fork) {\& unless (fork) {\& exec "what you really wanna do";\& die "exec failed!";\& }\& exit 0;\& }\& waitpid($pid, 0);.Ve.SpSee \*(L"Signals\*(R" in perlipc for other examples of code to do this.Zombies are not an issue with \f(CW\*(C`system("prog &")\*(C'\fR..Sh "How do I trap control characters/signals?".IX Subsection "How do I trap control characters/signals?"You don't actually \*(L"trap\*(R" a control character. Instead, that charactergenerates a signal which is sent to your terminal's currentlyforegrounded process group, which you then trap in your process.Signals are documented in \*(L"Signals\*(R" in perlipc and thesection on \*(L"Signals\*(R" in the Camel..PPYou can set the values of the \f(CW%SIG\fR hash to be the functions you wantto handle the signal. After perl catches the signal, it looks in \f(CW%SIG\fRfor a key with the same name as the signal, then calls the subroutinevalue for that key..PP.Vb 1\& # as an anonymous subroutine\&\& $SIG{INT} = sub { syswrite(STDERR, "ouch\en", 5 ) };\&\& # or a reference to a function\&\& $SIG{INT} = \e&ouch;\&\& # or the name of the function as a string\&\& $SIG{INT} = "ouch";.Ve.PPPerl versions before 5.8 had in its C source code signal handlers whichwould catch the signal and possibly run a Perl function that you had setin \f(CW%SIG\fR. This violated the rules of signal handling at that levelcausing perl to dump core. Since version 5.8.0, perl looks at \f(CW%SIG\fR*after* the signal has been caught, rather than while it is being caught.Previous versions of this answer were incorrect..Sh "How do I modify the shadow password file on a Unix system?".IX Subsection "How do I modify the shadow password file on a Unix system?"If perl was installed correctly and your shadow library was writtenproperly, the getpw*() functions described in perlfunc should intheory provide (read-only) access to entries in the shadow passwordfile. To change the file, make a new shadow password file (the formatvaries from system to system\*(--see passwd for specifics) and use\&\fIpwd_mkdb\fR\|(8) to install it (see pwd_mkdb for more details)..Sh "How do I set the time and date?".IX Subsection "How do I set the time and date?"Assuming you're running under sufficient permissions, you should beable to set the system-wide date and time by running the \fIdate\fR\|(1)program. (There is no way to set the time and date on a per-processbasis.) This mechanism will work for Unix, MS-DOS, Windows, and \s-1NT\s0;the \s-1VMS\s0 equivalent is \f(CW\*(C`set time\*(C'\fR..PPHowever, if all you want to do is change your time zone, you canprobably get away with setting an environment variable:.PP.Vb 3\& $ENV{TZ} = "MST7MDT"; # unixish\& $ENV{\*(AqSYS$TIMEZONE_DIFFERENTIAL\*(Aq}="\-5" # vms\& system "trn comp.lang.perl.misc";.Ve.Sh "How can I \fIsleep()\fP or \fIalarm()\fP for under a second?".IX Xref "Time::HiRes BSD::Itimer sleep select".IX Subsection "How can I sleep() or alarm() for under a second?"If you want finer granularity than the 1 second that the \f(CW\*(C`sleep()\*(C'\fRfunction provides, the easiest way is to use the \f(CW\*(C`select()\*(C'\fR function asdocumented in \*(L"select\*(R" in perlfunc. Try the \f(CW\*(C`Time::HiRes\*(C'\fR andthe \f(CW\*(C`BSD::Itimer\*(C'\fR modules (available from \s-1CPAN\s0, and starting fromPerl 5.8 \f(CW\*(C`Time::HiRes\*(C'\fR is part of the standard distribution)..Sh "How can I measure time under a second?".IX Xref "Time::HiRes BSD::Itimer sleep select".IX Subsection "How can I measure time under a second?"(contributed by brian d foy).PPThe \f(CW\*(C`Time::HiRes\*(C'\fR module (part of the standard distribution as ofPerl 5.8) measures time with the \f(CW\*(C`gettimeofday()\*(C'\fR system call, whichreturns the time in microseconds since the epoch. If you can't install\&\f(CW\*(C`Time::HiRes\*(C'\fR for older Perls and you are on a Unixish system, youmay be able to call \f(CWgettimeofday(2)\fR directly. See\&\*(L"syscall\*(R" in perlfunc..Sh "How can I do an \fIatexit()\fP or \fIsetjmp()\fP/\fIlongjmp()\fP? (Exception handling)".IX Subsection "How can I do an atexit() or setjmp()/longjmp()? (Exception handling)"Release 5 of Perl added the \s-1END\s0 block, which can be used to simulate\&\fIatexit()\fR. Each package's \s-1END\s0 block is called when the program orthread ends (see perlmod manpage for more details)..PPFor example, you can use this to make sure your filter programmanaged to finish its output without filling up the disk:.PP.Vb 3\& END {\& close(STDOUT) || die "stdout close failed: $!";\& }.Ve.PPThe \s-1END\s0 block isn't called when untrapped signals kill the program,though, so if you use \s-1END\s0 blocks you should also use.PP.Vb 1\& use sigtrap qw(die normal\-signals);.Ve.PPPerl's exception-handling mechanism is its \fIeval()\fR operator. You canuse \fIeval()\fR as setjmp and \fIdie()\fR as longjmp. For details of this, seethe section on signals, especially the time-out handler for a blocking\&\fIflock()\fR in \*(L"Signals\*(R" in perlipc or the section on \*(L"Signals\*(R" inthe Camel Book..PPIf exception handling is all you're interested in, try theexceptions.pl library (part of the standard perl distribution)..PPIf you want the \fIatexit()\fR syntax (and an \fIrmexit()\fR as well), try theAtExit module available from \s-1CPAN\s0..ie n .Sh "Why doesn't my sockets program work under System V (Solaris)? What does the error message ""Protocol not supported"" mean?".el .Sh "Why doesn't my sockets program work under System V (Solaris)? What does the error message ``Protocol not supported'' mean?".IX Subsection "Why doesn't my sockets program work under System V (Solaris)? What does the error message Protocol not supported mean?"Some Sys-V based systems, notably Solaris 2.X, redefined some of thestandard socket constants. Since these were constant across allarchitectures, they were often hardwired into perl code. The properway to deal with this is to \*(L"use Socket\*(R" to get the correct values..PPNote that even though SunOS and Solaris are binary compatible, thesevalues are different. Go figure..Sh "How can I call my system's unique C functions from Perl?".IX Subsection "How can I call my system's unique C functions from Perl?"In most cases, you write an external module to do it\*(--see the answerto \*(L"Where can I learn about linking C with Perl? [h2xs, xsubpp]\*(R".However, if the function is a system call, and your system supports\&\fIsyscall()\fR, you can use the syscall function (documented inperlfunc)..PPRemember to check the modules that came with your distribution, and\&\s-1CPAN\s0 as well\*(--someone may already have written a module to do it. OnWindows, try Win32::API. On Macs, try Mac::Carbon. If no modulehas an interface to the C function, you can inline a bit of C in yourPerl source with Inline::C..Sh "Where do I get the include files to do \fIioctl()\fP or \fIsyscall()\fP?".IX Subsection "Where do I get the include files to do ioctl() or syscall()?"Historically, these would be generated by the h2ph tool, part of thestandard perl distribution. This program converts \fIcpp\fR\|(1) directivesin C header files to files containing subroutine definitions, like&SYS_getitimer, which you can use as arguments to your functions.It doesn't work perfectly, but it usually gets most of the job done.Simple files like \fIerrno.h\fR, \fIsyscall.h\fR, and \fIsocket.h\fR were fine,but the hard ones like \fIioctl.h\fR nearly always need to hand-edited.Here's how to install the *.ph files:.PP.Vb 3\& 1. become super\-user\& 2. cd /usr/include\& 3. h2ph *.h */*.h.Ve.PPIf your system supports dynamic loading, for reasons of portability andsanity you probably ought to use h2xs (also part of the standard perldistribution). This tool converts C header files to Perl extensions.See perlxstut for how to get started with h2xs..PPIf your system doesn't support dynamic loading, you still probablyought to use h2xs. See perlxstut and ExtUtils::MakeMaker formore information (in brief, just use \fBmake perl\fR instead of a plain\&\fBmake\fR to rebuild perl with a new static extension)..Sh "Why do setuid perl scripts complain about kernel problems?".IX Subsection "Why do setuid perl scripts complain about kernel problems?"Some operating systems have bugs in the kernel that make setuidscripts inherently insecure. Perl gives you a number of options(described in perlsec) to work around such systems..Sh "How can I open a pipe both to and from a command?".IX Subsection "How can I open a pipe both to and from a command?"The IPC::Open2 module (part of the standard perl distribution) is aneasy-to-use approach that internally uses \fIpipe()\fR, \fIfork()\fR, and \fIexec()\fR to dothe job. Make sure you read the deadlock warnings in its documentation,though (see IPC::Open2). See\&\*(L"Bidirectional Communication with Another Process\*(R" in perlipc and\&\*(L"Bidirectional Communication with Yourself\*(R" in perlipc.PPYou may also use the IPC::Open3 module (part of the standard perldistribution), but be warned that it has a different order ofarguments from IPC::Open2 (see IPC::Open3)..Sh "Why can't I get the output of a command with \fIsystem()\fP?".IX Subsection "Why can't I get the output of a command with system()?"You're confusing the purpose of \fIsystem()\fR and backticks (``). \fIsystem()\fRruns a command and returns exit status information (as a 16 bit value:the low 7 bits are the signal the process died from, if any, andthe high 8 bits are the actual exit value). Backticks (``) run acommand and return what it sent to \s-1STDOUT\s0..PP.Vb 2\& $exit_status = system("mail\-users");\& $output_string = \`ls\`;.Ve.Sh "How can I capture \s-1STDERR\s0 from an external command?".IX Subsection "How can I capture STDERR from an external command?"There are three basic ways of running external commands:.PP.Vb 3\& system $cmd; # using system()\& $output = \`$cmd\`; # using backticks (\`\`)\& open (PIPE, "cmd |"); # using open().Ve.PPWith \fIsystem()\fR, both \s-1STDOUT\s0 and \s-1STDERR\s0 will go the same place as thescript's \s-1STDOUT\s0 and \s-1STDERR\s0, unless the \fIsystem()\fR command redirects them.Backticks and \fIopen()\fR read \fBonly\fR the \s-1STDOUT\s0 of your command..PPYou can also use the \fIopen3()\fR function from IPC::Open3. BenjaminGoldberg provides some sample code:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -