![JAR search and dependency download from the Maven repository](/logo.png)
com.github.jlangch.venice.shell.venice Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of venice Show documentation
Show all versions of venice Show documentation
Venice, a Lisp implemented in Java
;;;; __ __ _
;;;; \ \ / /__ _ __ (_) ___ ___
;;;; \ \/ / _ \ '_ \| |/ __/ _ \
;;;; \ / __/ | | | | (_| __/
;;;; \/ \___|_| |_|_|\___\___|
;;;;
;;;;
;;;; Copyright 2017-2024 Venice
;;;;
;;;; Licensed under the Apache License, Version 2.0 (the "License");
;;;; you may not use this file except in compliance with the License.
;;;; You may obtain a copy of the License at
;;;;
;;;; http://www.apache.org/licenses/LICENSE-2.0
;;;;
;;;; Unless required by applicable law or agreed to in writing, software
;;;; distributed under the License is distributed on an "AS IS" BASIS,
;;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;;; See the License for the specific language governing permissions and
;;;; limitations under the License.
;;;; Shell utilities
;;;; java macos unix windows
;;;; (shell/open url) 8+ x x x
;;;; (shell/open-macos-app name) 8+ x - -
;;;; (shell/diff file1 file2) 8+ x x x
;;;; (shell/kill pid) 9+ x x x
;;;; (shell/kill-forcibly pid) 9+ x x x
;;;; (shell/wait-for-process-exit pid timeout) 9+ x x x
;;;; (shell/alive? pid) 9+ x x x
;;;; (shell/pid) 9+ x x x
;;;; (shell/pid p) 9+ x x x
;;;; (shell/process-handle p) 9+ x x x
;;;; (shell/process-handle? p) 9+ x x x
;;;; (shell/process-info p) 9+ x x x
;;;; (shell/processes) 9+ x x x
;;;; (shell/processes-info) 9+ x x x
;;;; (shell/descendant-processes) 9+ x x x
;;;; (shell/parent-process) 9+ x x x
(ns shell)
(defn
^{ :arglists '("(require-mac-or-linux)")
:doc """
Validates if the OS is Mac OSX or Linux, throws an exception if not.
"""
:examples '(
"(shell/require-mac-or-linux)") }
require-mac-or-linux []
(when-not (or (os-type? :mac-osx) (os-type? :linux))
(throw (ex :VncException "Can only run on Mac OSX or Linux!"))))
(defn
^{ :arglists '("(require-windows)")
:doc """
Validates if the OS isWindows, throws an exception if not.
"""
:examples '(
"(shell/require-windows)") }
require-windows []
(when-not (os-type? :windows)
(throw (ex :VncException "Can only run on Windows!"))))
(defn
^{ :arglists '("(require-java-9+)")
:doc """
Validates if the Java VM is of version 9 or newer.
"""
:examples '(
"(shell/require-java-9+)") }
require-java-9+ []
(when (< (java-major-version) 9)
(throw (ex :VncException "Can only run on a Java VM 9+!"))))
(defn
^{ :arglists '("(diff file1 file2)")
:doc "Compare two files and print the differences."
:examples '("""(diff "/tmp/x.txt" "/tmp/y.txt")""") }
diff [file1 file2]
(case (os-type)
:mac-osx (sh "diff" (str file1) (str file2))
:linux (sh "diff" (str file1) (str file2))
:windows (sh "cmd" "/C" "FC" (str file1) (str file2))))
(defn
^{ :arglists '("(open url)")
:doc
"""
Opens a file or an url with the associated platform specific
application.
"""
:examples '(
"""(shell/open "img.png")"""
"""(shell/open "https://www.heise.de/")""")
:see-also '(
"shell/open-macos-app") }
open [url]
(sh/open (str url)))
(defn
^{ :arglists '("(open-macos-app name & args)")
:doc "Opens a Mac OSX app."
:examples '(
"""(shell/open-macos-app "Calendar")""",
"""(shell/open-macos-app "Maps")""",
"""(shell/open-macos-app "TextEdit" "example.txt")""")
:see-also '(
"shell/open") }
open-macos-app [name & args]
(when-not (os-type? :mac-osx)
(throw (ex :VncException "Can only open a Mac OSX applicaton on Mac OSX!")))
(if (empty? args)
(sh "/usr/bin/open" "-a" name)
(apply sh "/usr/bin/open" "-a" name args)))
(defn
^{ :arglists '(
"(pid)"
"(pid process-handle)")
:doc
"""
Without argument returns the PID (type long) of this process. With
a process-handle (:java.lang.ProcessHandle) returns the PID for the
process represented by the handle.
Requires Java 9+.
"""
:examples '(
"(shell/pid)")
:see-also '(
"shell/process-handle"
"shell/process-info"
"shell/alive?"
"shell/kill"
"shell/processes" ) }
pid
([]
(require-java-9+)
(-> (. :java.lang.ProcessHandle :current)
(. :pid)))
([process-handle]
(require-java-9+)
(. process-handle :pid)))
(defn
^{ :arglists '("(process-handle pid)")
:doc
"""
Returns the process handle (:java.lang.ProcessHandle) for a PID or
nil if there is no process.
Requires Java 9+.
"""
:examples '(
"(shell/process-handle 4556)")
:see-also '(
"shell/pid"
"shell/alive?"
"shell/process-info"
"shell/kill" ) }
process-handle [pid]
(require-java-9+)
(if (process-handle? pid)
pid
(-<> (. :java.lang.ProcessHandle :of pid)
(. <> :orElse nil)
(cast :java.lang.ProcessHandle <>))))
(defn
^{ :arglists '("(process-handle? p)")
:doc
"""
Returns true if p is a process handle (:java.lang.ProcessHandle).
Requires Java 9+.
""" }
process-handle? [p]
(instance-of? :java.lang.ProcessHandle p))
(defn
^{ :arglists '("(processes)")
:doc
"""
Returns a snapshot of all processes visible to the current process.
Returns a list of :java.lang.ProcessHandle for the processes.
Requires Java 9+.
"""
:examples '(
"""
(shell/processes)
"""
"""
;; find the PID of the ArangoDB process
;; like: pgrep -lf ArangoDB3 | cut -d ' ' -f 1
(->> (shell/processes)
(map shell/process-info)
(filter #(str/contains? (:command-line %) "ArangoDB3"))
(map :pid))
""")
:see-also '(
"shell/processes-info") }
processes []
(require-java-9+)
(->> (. :java.lang.ProcessHandle :allProcesses)
(seq)
(map #(cast :java.lang.ProcessHandle %))))
(defn
^{ :arglists '("(processes-info)")
:doc
"""
Returns a snapshot of all processes visible to the current process.
Returns a list of process infos for the processes.
The process info is a map with the keys:
| :pid | the PID |
| :alive | true if the process is alive else false |
| :arguments | the list of strings of the arguments of the process |
| :command | the executable pathname of the process |
| :command-line | the command line of the process |
| :start-time | the start time of the process |
| :total-cpu-millis | the total cputime accumulated of the process |
| :user | the user of the process. |
Requires Java 9+.
"""
:examples '(
"""
(shell/processes-info)
"""
"""
;; find the PID of the ArangoDB process
;; like: pgrep -lf ArangoDB3 | cut -d ' ' -f 1
(->> (shell/processes-info)
(filter #(str/contains? (:command-line %) "ArangoDB3"))
(map :pid))
""")
:see-also '(
"shell/processes") }
processes-info []
(require-java-9+)
(->> (shell/processes)
(map shell/process-info)))
(defn
^{ :arglists '(
"(alive? pid)"
"(alive? process-handle)")
:doc
"""
Returns true if the process represented by a PID or a process handle
is alive otherwise false.
Requires Java 9+.
"""
:examples '("(shell/alive? 4556)")
:see-also '("shell/pid" "shell/processes") }
alive? [p]
(require-java-9+)
(let [handle (process-handle p)]
(if (some? handle)
(. handle :isAlive)
false)))
(defn
^{ :arglists '(
"(process-info pid)"
"(process-info process-handle)")
:doc
"""
Returns the process info for a process represented by a PID or a
process handle.
The process info is a map with the keys:
| :pid | the PID |
| :alive | true if the process is alive else false |
| :arguments | the list of strings of the arguments of the process |
| :command | the executable pathname of the process |
| :command-line | the command line of the process |
| :start-time | the start time of the process |
| :total-cpu-millis | the total cputime accumulated of the process |
| :user | the user of the process. |
Requires Java 9+.
"""
:examples '(
"""
(shell/process-info 4556)
"""
"""
;; find the PID of the ArangoDB process
;; like: pgrep -lf ArangoDB3 | cut -d ' ' -f 1
(->> (shell/processes)
(map shell/process-info)
(filter #(str/contains? (:command-line %) "ArangoDB3"))
(map :pid))
""")
:see-also '(
"shell/pid" "shell/process-handle ") }
process-info [p]
(require-java-9+)
(let [handle (process-handle p)]
(when (some? handle)
(let [get-or-nil (fn [obj key] (java-unwrap-optional (. obj key)))
map-instant (fn [x] (if x (time/local-date-time x) nil))
map-duration (fn [x] (if x (/ (. x :toNanos) 1_000_000) nil))
info (. handle :info)]
(hash-map
:pid (shell/pid handle)
:alive (shell/alive? handle)
:arguments (get-or-nil info :arguments)
:command (get-or-nil info :command)
:command-line (get-or-nil info :commandLine)
:start-time (->> (get-or-nil info :startInstant)
(cast :java.time.Instant)
(map-instant))
:total-cpu-millis (->> (get-or-nil info :totalCpuDuration)
(cast :java.time.Duration)
(map-duration))
:user (get-or-nil info :user))))))
(defn
^{ :arglists '(
"(current-process)")
:doc
"""
Returns the process handle of the current process.
Requires Java 9+.
"""
:examples '(
"(shell/current-process)"
"(shell/process-info (shell/current-process))")
:see-also '(
"shell/current-process-info" "shell/process-info") }
current-process []
(require-java-9+)
(->> (. :java.lang.ProcessHandle :current)
(cast :java.lang.ProcessHandle)))
(defn
^{ :arglists '(
"(descendant-processes pid)"
"(descendant-processes process-handle)")
:doc
"""
Returns the descendants (:java.lang.ProcessHandle) of a process
represented by a PID or a process handle.
Requires Java 9+.
"""
:examples '(
"(shell/descendant-processes 4556)"
"""
(->> (shell/current-process)
(shell/descendant-processes)
(map shell/process-info))
""" )
:see-also '(
"shell/process-info" "shell/pid") }
descendant-processes [p]
(require-java-9+)
(if-let [handle (process-handle p)]
(->> (. handle :descendants)
(seq)
(map #(cast :java.lang.ProcessHandle %)))))
(defn
^{ :arglists '(
"(parent-process pid)"
"(parent-process process-handle)")
:doc
"""
Returns the parent (:java.lang.ProcessHandle) of a process represented
by a PID or a process handle.
Requires Java 9+.
"""
:examples '(
"(shell/parent-process 4556)"
"""
(->> (shell/current-process)
(shell/parent-process)
(shell/process-info))
""")
:see-also '(
"shell/process-info" "shell/pid" "shell/processes") }
parent-process [p]
(require-java-9+)
(if-let [handle (process-handle p)]
(->> (. handle :parent)
(java-unwrap-optional)
(cast :java.lang.ProcessHandle))))
(defn
^{ :arglists '(
"(kill pid)"
"(kill process-handle)")
:doc
"""
Requests the process to be killed. Returns true if the process is
killed and false if the process stays alive. Returns nil if the
process does not exist. Accepts a PID or a process handle
(:java.lang.ProcessHandle).
Requires Java 9+.
"""
:examples '(
"(shell/kill 4556)")
:see-also '(
"shell/pid" "shell/kill-forcibly" "shell/processes") }
kill [p]
(require-java-9+)
(if-let [handle (process-handle p)]
(. handle :destroy)))
(defn
^{ :arglists '(
"(kill-forcibly pid)"
"(kill-forcibly process-handle)")
:doc
"""
Requests the process to be killed forcibly. Returns true if the process
is killed and false if the process stays alive. Returns nil if the
process does not exist. Accepts a PID or a process handle
(:java.lang.ProcessHandle).
Requires Java 9+.
"""
:examples '(
"(shell/kill-forcibly 4556)")
:see-also '(
"shell/pid" "shell/kill" "shell/processes") }
kill-forcibly [p]
(require-java-9+)
(if-let [handle (process-handle p)]
(. handle :destroyForcibly)))
(defn
^{ :arglists '(
"(wait-for-process-exit pid timeout)"
"(wait-for-process-exit process-handle timeout)")
:doc
"""
Waits until the process with the pid exits. Waits max timeout
seconds. Returns nil if the process exits before reaching the
timeout, else the pid is returned. Accepts a PID or a
process handle (:java.lang.ProcessHandle).
Requires Java 9+.
"""
:examples '(
"(shell/wait-for-process-exit 12345 20)")
:see-also '(
"shell/pid" "shell/kill" "shell/processes") }
wait-for-process-exit [p timeout]
(require-java-9+)
(let [handle (process-handle p)]
(if (some? handle)
(let [future (. handle :onExit)]
(try
(. future :get timeout :SECONDS)
nil
(catch :java.lang.Exception e))))
(pid handle)))
© 2015 - 2025 Weber Informatics LLC | Privacy Policy