I want to use common lisp for scripting, and connecting to a remote computer over ssh and sending some commands. The easiest way seems to be to use clisp's ext:run-shell-command, documentation here, and then read from and write to resulting stream. If there is a better way let me know. When I try this:
[5]> (setf shell-str (ext:run-shell-command "ssh remotecomp" :input :stream :output :stream))
#<IO TWO-WAY-STREAM #<INPUT BUFFERED PIPE-INPUT-STREAM CHARACTER 1204> #<OUTPUT BUFFERED PIPE-OUTPUT-STREAM CHARACTER 1204>>
[6]> Pseudo-terminal will not be allocated because stdin is not a terminal.
The process in the inferior-lisp-buffer hangs and has to be killed with C-c c. However the shell-str object does get created, but when I try to read from it there is no output there.
[9]> (read-line shell-str)
*** - READ: input stream
#<IO TWO-WAY-STREAM #<INPUT BUFFERED PIPE-INPUT-STREAM CHARACTER 1204>
#<OUTPUT BUFFERED PIPE-OUTPUT-STREAM CHARACTER 1204>>
has reached its end
The following restarts are available:
ABORT :R1 Abort main loop
Running ext:run-shell-command with something like "ls -l" does work as expected. Running ssh in cygwin or even windows command prompt works as it should. I'm running clisp 2.49 and openssh 5.9p1 on windows 7.
Edit: Got it working by using no passwords and double -t arguments to ssh.
(setf str (ext:run-program "ssh" :arguments '("-t" "-t" "host") :output :stream :input :stream))
(format str "ls -l~%")
(finish-output str)
(read-line str)
Snowape found a solution for clisp. Here's a working version of that solution for CCL:
? (run-program "ssh" '("-t" "-t" "[user]@[ip]") :output :stream :input :stream :wait nil)
#<EXTERNAL-PROCESS (ssh -t -t ...)[65909] (RUNNING) #x302000A2335D>
? (setf *t* *)
#<EXTERNAL-PROCESS (ssh -t -t ...)[65909] (RUNNING) #x302000A2335D>
? (setf *in* (external-process-input-stream *t*))
#<BASIC-CHARACTER-OUTPUT-STREAM ISO-8859-1 (PIPE/17) #x302000A2304D>
? (setf *out* (external-process-output-stream *t*))
#<BASIC-CHARACTER-INPUT-STREAM ISO-8859-1 (PIPE/18) #x302000A22ABD>
? (read-line *out*)
"Last login: ...
NIL
? (read-line *out*)
"Have a lot of fun...
NIL
? (format *in* "ls -l~%")
NIL
? (finish-output *in*)
NIL
? (read-line *out*)
"user@ip:~> ls -l
NIL
? (read-line *out*)
"total 0
[etc.]
As an alternative approach, you could load up the Trivial Shell package using Quicklisp, and then launch a shell process from within the lisp session that does the scripting (would have the ssh command within it). I've never tried Trivial Shell within Windows though, so not sure how that would behave.