Reputation: 5841
I am wondering if there is a way to get Linux's PID (Process ID) from Common Lisp's REPL. That is, I would like to know the ID of the SBCL or Allegro process from the REPL of the process itself.
Upvotes: 4
Views: 527
Reputation: 10108
Final Solution (to the biggest part by @Dan Robertson's and @coredump - thank you guys!)
Actually @Dan Robertson gave the full answer - I realize in retrospect. This answer is just the implementation of what he said. So give him the points!
(ql:quickload "CL-PPCRE") ;; for regex parsing
(defun get-this-pid ()
"Return PID of this current lisp process."
(with-open-file (in #P"/proc/self/status")
(loop for line = (read-line in nil)
while line
when (ppcre:scan "^Pid" line)
do (return (car
(ppcre:all-matches-as-strings "\\d+"
line))))))
;; to get current process id, call:
(get-this-pid) ;
;; returns for me at the moment using sbcl "12646"
;; this is correct as closing of all other sbcl processes
;; and doing "pidof sbcl" in the shell showed.
As @Don Robertson pointed out, the file /proc/self/status
shows the program which opens it its "PID" number (every program sees it differently). Thank you Don, since this solves the problem of finding really the PID of the program (pidof sbcl
in the shell would give several numbers if several lisp programs are running independently on the machine.
Calling external programs is obsolete, if we open this file then from within cl, like @coredump pointed out.
PID numbers of other programs
;; Thanks to @coredump - who suggested to use
;; `ppcre:split :whitespace-char-class` for capturing arbitrary numbers
;; in the answer string - I added a test for integer-string-p to clean
;; non-numberic values after split.
(ql:quickload "CL-PPCRE")
(defun integer-string-p (string)
"Does string constist only of '01234567890' characters?"
(reduce (lambda (x y) (and x y))
(mapcar (lambda (c) (member c (coerce "1234567890" 'list)))
(coerce string 'list))))
(defun extract-integers-from-string (s)
"Return integer-words of s."
(let ((l (ppcre:split :whitespace-char-class s)))
(remove-if-not #'integer-string-p l)))
(defun pid-numbers (program-name)
"Return PID numbers of a program in current machine."
(let ((pid-line (with-output-to-string (out)
(external-program:run "pidof" (list program-name)
:output out))))
(extract-integers-from-string pid-line)))
;; call it
(pid-numbers "sbcl")
(pid-numbers "firefox")
;; * (pid-numbers "sbcl")
;; ("16636" "12346")
;; * (pid-numbers "firefox")
;; ("24931" "19388" "19122" "10800" "10745") ; yeah I have many open :D
Upvotes: 4
Reputation: 4360
There is a (basically) portable way to do this. CL provides for reading files and one can observe that the pid of the current process is in /proc/self/status
(also /proc/self
is a symlink to the process’ pid but I don’t think there’s a portable read link).
Specifically /proc/self/status
is a text file and contains a line that looks like:
Pid: 439
So you could parse the file to extract that.
But then once you have the pid there isn’t much you can do with it without system calls or /proc
weirdness
Upvotes: 6
Reputation: 782693
There's nothing in the Common Lisp specification that implements this. Process IDs are too implementation-dependent.
In SBCL, the SB-POSIX
package provides Lisp interfaces to most POSIX system calls, so you would use (sb-posix:getpid)
.
In Allegro CL, operating system interface functions are in the EXCL.OSI
package, so you would use (excl.ose:getpid)
Upvotes: 8