summaryrefslogtreecommitdiff
path: root/modules/ssh/dist
diff options
context:
space:
mode:
authorArtyom V. Poptsov <poptsov.artyom@gmail.com>2016-12-11 16:31:43 +0300
committerArtyom V. Poptsov <poptsov.artyom@gmail.com>2016-12-11 16:46:57 +0300
commit9bb9a06b9cc6ba264e0297695612d295b66b72c9 (patch)
treee3641959e8b34e672e4ea916d618c350e8c37e71 /modules/ssh/dist
parentdist.scm (distribute, dist-map, execute-job): Use 'when' (diff)
downloadguile-ssh-9bb9a06b9cc6ba264e0297695612d295b66b72c9.tar.gz
node.scm: Implement a fallback pgrep
* modules/ssh/dist/node.scm (which, pgrep, fallback-pgrep): New procedures. (node-server-running?): Fallback to a Guile-SSH implementation of 'pgrep' if procps tools aren't available on a node; issue a libssh warning if fallback pgrep is used.
Diffstat (limited to 'modules/ssh/dist')
-rw-r--r--modules/ssh/dist/node.scm84
1 files changed, 72 insertions, 12 deletions
diff --git a/modules/ssh/dist/node.scm b/modules/ssh/dist/node.scm
index 73376c3..0492a7c 100644
--- a/modules/ssh/dist/node.scm
+++ b/modules/ssh/dist/node.scm
@@ -60,6 +60,7 @@
#:use-module (ssh channel)
#:use-module (ssh popen)
#:use-module (ssh tunnel)
+ #:use-module (ssh log)
#:export (node?
node-session
node-tunnel
@@ -265,29 +266,88 @@ result, a number of the evaluation, a module name and a language name. Throw
(rrepl-get-result rrepl-channel))
+;;; Remote shell
+
+(define (which node program-name)
+ "Check if a PROGRAM-NAME is available on a NODE. Return two values: a check
+result and a return code."
+ (rexec node (format #f "which '~a'" program-name)))
+
+(define* (pgrep node pattern #:key (full? #f))
+ "Check if a process with a PATTERN cmdline is available on a NODE.
+Return two values: a check result and a return code."
+ (rexec node (format #f "pgrep ~a '~a'"
+ (if full? "--full" "")
+ pattern)))
+
+(define (fallback-pgrep node pattern)
+ "Guile-SSH implementation of 'pgrep' that uses pure bash and '/proc'
+filesystem. Check if a process with a PATTERN cmdline is available on a NODE.
+Return two values: a check result and a return code."
+ (let ((ptrn (string-append (regexp-substitute/global #f " " pattern
+ 'pre "?" 'post)
+ ".*")))
+ (rexec node
+ (string-append
+ "echo '"
+ "for p in $(ls /proc); do"
+ " if [[ \"$p\" =~ ^[0-9]+ ]]; then"
+ " name=$(cat \"/proc/$p/status\" 2>/dev/null | head -1);"
+ " if [[ \"$name\" =~ Name:.*guile ]]; then"
+ " cmdline=$(cat \"/proc/$p/cmdline\");"
+ (format #f " if [[ \"$cmdline\" =~~ ~a ]]; then" ptrn)
+ " exit 0;"
+ " fi;"
+ " fi;"
+ " fi;"
+ "done;"
+ "exit 1;"
+ "' | bash"))))
+
+
;;;
(define (node-server-running? node)
"Check if a RREPL is running on a NODE, return #t if it is running and
listens on an expected port, return #f otherwise."
+ (define (pgrep-available?)
+ "Check if 'pgrep' from procps is available on the node."
+ (receive (result rc)
+ (which node "pgrep")
+ (zero? rc)))
(define (guile-up-and-running?)
(let ((rp (tunnel-open-forward-channel (node-tunnel node))))
(and (channel-open? rp)
(let ((line (read-line rp)))
(close rp)
(and (not (eof-object? line)))
- (string-match "^GNU Guile .*" line)))))
- (receive (result rc)
- (rexec node (format #f "pgrep --full 'guile --listen=~a'"
- (node-repl-port node)))
- (or (and (zero? rc)
- (guile-up-and-running?))
- ;; Check the default port.
- (and (= (node-repl-port node) %guile-default-repl-port)
- (receive (result rc)
- (rexec node "pgrep --full 'guile --listen'")
- (and (zero? rc)
- (guile-up-and-running?)))))))
+ (string-match "^GNU Guile .*" line)))))
+
+ (let ((pgrep? (pgrep-available?)))
+ (unless pgrep?
+ (format-log 'rare
+ "node-server-running?"
+ (string-append
+ "WARNING: 'pgrep' from procps is not available on the node"
+ " ~a; falling back to the Guile-SSH pgrep implementation")
+ node))
+ (receive (result rc)
+ (if pgrep?
+ (pgrep node (format #f "guile --listen=~a"
+ (node-repl-port node))
+ #:full? #t)
+ (fallback-pgrep node (format #f "guile --listen=~a"
+ (node-repl-port node))))
+ (or (and (zero? rc)
+ (guile-up-and-running?))
+ ;; Check the default port.
+ (and (= (node-repl-port node) %guile-default-repl-port)
+ (receive (result rc)
+ (if pgrep?
+ (pgrep node "guile --listen" #:full? #t)
+ (fallback-pgrep "guile --listen"))
+ (and (zero? rc)
+ (guile-up-and-running?))))))))
(define (node-run-server node)