📄 expect.pod
字号:
=head2 I want to automate password entry for su/ssh/scp/rsh/...You shouldn't use Expect for this. Putting passwords, especially root passwords, into scripts in clear text can mean severe security problems. I strongly recommend using other means. For 'su', consider switching to 'sudo', which gives you root access on a per-command and per-user basis without the need to enter passwords. 'ssh'/'scp' can be set up with RSA authentication without passwords. 'rsh' can use the .rhost mechanism, but I'd strongly suggest to switch to 'ssh'; to mention 'rsh' and 'security' in the same sentence makes an oxymoron. It will work for 'telnet', though, and there are valid uses for it,but you still might want to consider using 'ssh', as keeping cleartextpasswords around is very insecure.=head2 I want to use Expect to automate [anything with a buzzword]...Are you sure there is no other, easier way? As a rule of thumb,Expect is useful for automating things that expect to talk to a human,where no formal standard applies. For other tasks that do follow awell-defined protocol, there are often better-suited modules thatalready can handle those protocols. Don't try to do HTTP requests byspawning telnet to port 80, use LWP instead. To automate FTP, take alook at L<Net::FTP> or C<ncftp> (http://www.ncftp.org). You don't usea screwdriver to hammer in your nails either, or do you?=head2 Is it possible to use threads with Expect?Basically yes, with one restriction: you must spawn() your programs inthe main thread and then pass the Expect objects to the handlingthreads. The reason is that spawn() uses fork(), and L<perlthrtut>: "Thinking of mixing fork() and threads? Please lie down and wait until the feeling passes."=head2 I want to log the whole session to a file.Use $exp->log_file("filename");or $exp->log_file($filehandle);or even $exp->log_file(\&log_procedure);for maximum flexibility.Note that the logfile is appended to by default, but you canspecify an optional mode "w" to truncate the logfile: $exp->log_file("filename", "w");To stop logging, just call it with a false argument: $exp->log_file(undef);=head2 How can I turn off multi-line matching for my regexps?To globally unset multi-line matching for all regexps: $Expect::Multiline_Matching = 0;You can do that on a per-regexp basis by stating C<(?-m)> inside the regexp(you need perl5.00503 or later for that).=head2 How can I expect on multiple spawned commands?You can use the B<-i> parameter to specify a single object or a listof Expect objects. All following patterns will be evaluated againstthat list.You can specify B<-i> multiple times to create groups of objectsand patterns to match against within the same expect statement.This works just like in Tcl/Expect.See the source example below.=head2 I seem to have problems with ptys!Well, pty handling is really a black magic, as it is extremely systemdependend. I have extensively revised IO-Tty, so these problemsshould be gone.If your system is listed in the "verified" list of IO::Tty, youprobably have some non-standard setup, e.g. you compiled yourLinux-kernel yourself and disabled ptys. Please ask your friendlysysadmin for help.If your system is not listed, unpack the latest version of IO::Tty,do a 'perl Makefile.PL; make; make test; uname C<-a>' and send me theresults and I'll see what I can deduce from that.=head2 I just want to read the output of a process without expect()ing anything. How can I do this?[ Are you sure you need Expect for this? How about qx() or open("prog|")? ]By using expect without any patterns to match. $process->expect(undef); # Forever until EOF $process->expect($timeout); # For a few seconds $process->expect(0); # Is there anything ready on the handle now?=head2 Ok, so now how do I get what was read on the handle? $read = $process->before();=head2 Where's IO::Pty?Find it on CPAN as IO-Tty, which provides both.=head2 How come when I automate the passwd program to change passwords for me passwd dies before changing the password sometimes/every time?What's happening is you are closing the handle before passwd exits.When you close the handle to a process, it is sent a signal (SIGPIPE?)telling it that STDOUT has gone away. The default behavior forprocesses is to die in this circumstance. Two ways you can make thisnot happen are: $process->soft_close();This will wait 15 seconds for a process to come up with an EOF byitself before killing it. $process->expect(undef); This will wait forever for the process to match an empty set ofpatterns. It will return when the process hits an EOF.As a rule, you should always expect() the result of your transactionbefore you continue with processing.=head2 How come when I try to make a logfile with log_file() or set_group() it doesn't print anything after the last time I run expect()?Output is only printed to the logfile/group when Expect reads from theprocess, during expect(), send_slow() and interconnect().One way you can force this is to make use of $process->expect(undef); and $process->expect(0); which will make expect() run with an empty pattern set forever or justfor an instant to capture the output of $process. The output isavailable in the accumulator, so you can grab it using$process->before().=head2 I seem to have problems with terminal settings, double echoing, etc.Tty settings are a major pain to keep track of. If you find unexpectedbehavior such as double-echoing or a frozen session, doublecheck thedocumentation for default settings. When in doubt, handle themyourself using $exp->stty() and manual_stty() functions. As of .98you shouldn't have to worry about stty settings getting fouled unlessyou use interconnect or intentionally change them (like doing -echo toget a password).If you foul up your terminal's tty settings, kill any hung processesand enter 'stty sane' at a shell prompt. This should make yourterminal manageable again.Note that IO::Tty returns ptys with your systems default settingregarding echoing, CRLF translation etc. and Expect does not changethem. I have considered setting the ptys to 'raw' without anytranslation whatsoever, but this would break a lot of existing things,as '\r' translation would not work anymore. On the other hand, a rawpty works much like a pipe and is more WYGIWYE (what you get is whatyou expect), so I suggest you set it to 'raw' by yourself: $exp = new Expect; $exp->raw_pty(1); $exp->spawn(...);To disable echo: $exp->slave->stty(qw(-echo));=head2 I'm spawning a telnet/ssh session and then let the user interact with it. But screen-oriented applications on the other side don't work properly.You have to set the terminal screen size for that. Luckily, IO::Ptyalready has a method for that, so modify your code to look like this: my $exp = new Expect; $exp->slave->clone_winsize_from(\*STDIN); $exp->spawn("telnet somehost);Also, some applications need the TERM shell variable set so they knowhow to move the cursor across the screen. When logging in, the remoteshell sends a query (Ctrl-Z I think) and expects the terminal toanswer with a string, e.g. 'xterm'. If you really want to go that way(be aware, madness lies at its end), you can handle that and send backthe value in $ENV{TERM}. This is only a hand-waving explanation,please figure out the details by yourself.=head2 I set the terminal size as explained above, but if I resize the window, the application does not notice this.You have to catch the signal WINCH ("window size changed"), change theterminal size and propagate the signal to the spawned application: my $exp = new Expect; $exp->slave->clone_winsize_from(\*STDIN); $exp->spawn("ssh somehost); $SIG{WINCH} = \&winch; sub winch { $exp->slave->clone_winsize_from(\*STDIN); kill WINCH => $exp->pid if $exp->pid; $SIG{WINCH} = \&winch; } $exp->interact();There is an example file ssh.pl in the examples/ subdir that shows howthis works with ssh. Please note that I do strongly object againstusing Expect to automate ssh login, as there are better way to do that(see L<ssh-keygen>).=head2 I noticed that the test uses a string that resembles, but not exactly matches, a well-known sentence that contains every character. What does that mean?That means you are anal-retentive. :-) [Gotcha there!]=head2 I get a "Could not assign a pty" error when running as a non-root user on an IRIX box?The OS may not be configured to grant additional pty's (pseudo terminals)to non-root users. /usr/sbin/mkpts should be 4755, not 700 for thisto work. I don't know about security implications if you do this.=head2 How come I don't notice when the spawned process closes its stdin/out/err??You are probably on one of the systems where the master doesn't get anEOF when the slave closes stdin/out/err.One possible solution is when you spawn a process, follow it with aunique string that would indicate the process is finished. $process = Expect->spawn('telnet somehost; echo ____END____');And then $process->expect($timeout,'____END____','other','patterns');=head1 Source Examples=head2 How to automate login my $telnet = new Net::Telnet ("remotehost") # see Net::Telnet or die "Cannot telnet to remotehost: $!\n";; my $exp = Expect->exp_init($telnet); # deprecated use of spawned telnet command # my $exp = Expect->spawn("telnet localhost") # or die "Cannot spawn telnet: $!\n";; my $spawn_ok; $exp->expect($timeout, [ qr'login: $', sub { $spawn_ok = 1; my $fh = shift; $fh->send("$username\n"); exp_continue; } ], [ 'Password: $', sub { my $fh = shift; print $fh "$password\n"; exp_continue; } ], [ eof => sub { if ($spawn_ok) { die "ERROR: premature EOF in login.\n"; } else { die "ERROR: could not spawn telnet.\n"; } } ], [ timeout => sub { die "No login.\n"; } ], '-re', qr'[#>:] $', #' wait for shell prompt, then exit expect );=head2 How to expect on multiple spawned commands foreach my $cmd (@list_of_commands) { push @commands, Expect->spawn($cmd); } expect($timeout, '-i', \@commands, [ qr"pattern", # find this pattern in output of all commands sub { my $obj = shift; # object that matched print $obj "something\n"; exp_continue; # we don't want to terminate the expect call } ], '-i', $some_other_command, [ "some other pattern", sub { my ($obj, $parmref) = @_; # ... # now we exit the expect command }, \$parm ], );=head2 How to propagate terminal sizes my $exp = new Expect; $exp->slave->clone_winsize_from(\*STDIN); $exp->spawn("ssh somehost); $SIG{WINCH} = \&winch; sub winch { $exp->slave->clone_winsize_from(\*STDIN); kill WINCH => $exp->pid if $exp->pid; $SIG{WINCH} = \&winch; } $exp->interact();=head1 HOMEPAGEhttp://sourceforge.net/projects/expectperl/=head1 MAILING LISTSThere are two mailing lists available, expectperl-announce andexpectperl-discuss, at http://lists.sourceforge.net/lists/listinfo/expectperl-announceand http://lists.sourceforge.net/lists/listinfo/expectperl-discuss=head1 BUG TRACKINGYou can use the CPAN Request Tracker http://rt.cpan.org/ and submitnew bugs under http://rt.cpan.org/Ticket/Create.html?Queue=Expect=head1 AUTHORS(c) 1997 Austin Schutz E<lt>F<ASchutz@users.sourceforge.net>E<gt> (retired)expect() interface & functionality enhancements (c) 1999-2006 Roland Giersig.This module is now maintained by Roland Giersig E<lt>F<RGiersig@cpan.org>E<gt>=head1 LICENSEThis module can be used under the same terms as Perl.=head1 DISCLAIMERTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIEDWARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OFMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSSOF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ANDON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ORTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THEUSE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCHDAMAGE.In other words: Use at your own risk. Provided as is. Your mileagemay vary. Read the source, Luke!And finally, just to be sure:Any Use of This Product, in Any Manner Whatsoever, Will Increase theAmount of Disorder in the Universe. Although No Liability Is ImpliedHerein, the Consumer Is Warned That This Process Will Ultimately Leadto the Heat Death of the Universe.=cut
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -