123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- @c -*-texinfo-*-
- @c This file is part of Guile-SSH Reference Manual.
- @c Copyright (C) 2015 Artyom V. Poptsov
- @c See the file guile-ssh.texi for copying conditions.
- @node Remote Pipes
- @section Remote Pipes
- @cindex remote pipes
- @code{(ssh popen)} provides API for working with remote pipes, akin to
- @code{(ice-9 popen)} procedures (@pxref{Pipes,,, guile, The GNU Guile
- Reference Manual})
- @var{mode} argument allows to specify what kind of pipe should be created.
- Allowed values are: @code{OPEN_READ}, @code{OPEN_WRITE}, @code{OPEN_BOTH}.
- There is an additional value, @code{OPEN_PTY}, that allows to request a pseudo
- terminal. The terminal is needed to run such commands as @code{top}. Thus,
- to run @code{top} on the remote side you need to open a remote pipe with "t"
- flag set.
- @strong{Note} that when a PTY is used, a server merges stderr stream with
- stdout.
- Values of the aforementioned constants:
- @table @samp
- @item OPEN_READ
- ``r''
- @item OPEN_WRITE
- ``w''
- @item OPEN_BOTH
- ``r+''
- @item OPEN_PTY
- ``t''
- @end table
- @deffn {Scheme Procedure} open-remote-pipe session command mode
- Execute a @var{command} on the remote host using a @var{session} with a pipe
- to it. Returns newly created channel port with the specified @var{mode}.
- @end deffn
- @deffn {Scheme Procedure} open-remote-pipe* session mode prog [args...]
- Execute @var{prog} on the remote host with the given @var{args} using a
- @var{session} with a pipe to it. Returns newly created channel port with the
- specified @var{mode}.
- @end deffn
- @deffn {Scheme Procedure} open-remote-input-pipe session command
- @deffnx {Scheme Procedure} open-remote-input-pipe* session prog [args...]
- Equvalent to @code{open-remote-pipe} and @code{open-remote-pipe*} respectively
- with mode @code{OPEN_READ}.
- @end deffn
- @deffn {Scheme Procedure} open-remote-output-pipe session command
- @deffnx {Scheme Procedure} open-remote-output-pipe* session prog [args...]
- Equvalent to @code{open-remote-pipe} and @code{open-remote-pipe*} respectively
- with mode @code{OPEN_WRITE}.
- @end deffn
- @subsection Examples
- @subsubsection Simple cases
- Here's a self-explanatory little script that executes @code{uname -o} command
- on the local host and prints the result:
- @lisp
- #!/usr/bin/guile \
- -e main -s
- !#
- (use-modules (ice-9 rdelim) ; @{read,write@}-line
- ;; Guile-SSH
- (ssh session)
- (ssh auth)
- (ssh popen)) ; remote pipes
- (define (main args)
- ;; Make a session with local machine and the current user.
- (let ((session (make-session #:host "localhost")))
- ;; Connect the session and perform the authentication.
- (connect! session)
- (authenticate-server session)
- (userauth-agent! session)
- ;; Execute the command on the remote side and get the input pipe
- ;; to it.
- (let ((channel (open-remote-input-pipe session "uname -o")))
- ;; Read and display the result.
- (write-line (read-line channel)))))
- @end lisp
- @subsubsection Executing a command with a pseudo terminal
- Surely we aren't limited to one-line outputs; for example, we can watch
- @code{top} command executing on a remote side locally, by reading data from
- the channel in a loop:
- @lisp
- (define OPEN_PTY_READ (string-append OPEN_PTY OPEN_READ))
- (let ((channel (open-remote-pipe* session OPEN_PTY_READ
- "top" "-u avp")))
- (let r ((line (read-line channel)))
- (unless (eof-object? line)
- (write-line line)
- (r (read-line channel)))))
- @end lisp
- Or we can do the same, but this time with streams:
- @lisp
- (use-modules (srfi srfi-41) ; streams
- (ssh session)
- (ssh auth)
- (ssh popen))
- (define (pipe->stream p)
- (stream-let loop ((c (read-char p)))
- (if (eof-object? c)
- (begin
- (close-input-port p)
- stream-null)
- (stream-cons c (loop (read-char p))))))
- (define OPEN_PTY_READ (string-append OPEN_PTY OPEN_READ))
- (define (main args)
- (let ((s (make-session #:host "example.org")))
- (connect! s)
- (userauth-agent! s)
- (let ((rs (pipe->stream (open-remote-pipe* s OPEN_PTY_READ
- "top" "-u avp"))))
- (stream-for-each display rs))))
- @end lisp
- @subsubsection Controlling the pseudo terminal size
- To set the size of a pseudo terminal, one may use @code{channel-set-pty-size!}
- from @code{(ssh channel)}. For example:
- @lisp
- (use-modules (ssh popen)
- (ssh auth)
- (ssh channel))
- (define OPEN_PTY_READ (string-append OPEN_PTY OPEN_READ))
- ;; Opening of a Guile-SSH session goes here ...
- (let ((p (open-remote-pipe* session OPEN_PTY_READ "top" "-u avp")))
- (channel-set-pty-size! p 80 50)
- ;; Reading output from a port ...
- )
- @end lisp
- @c Local Variables:
- @c TeX-master: "guile-ssh.texi"
- @c End:
|