在 Linux 上获取通用 Lisp 进程 ID



我想知道是否有办法从Common Lisp的REPL中获取Linux的PID(进程ID(。也就是说,我想从流程本身的 REPL 中知道 SBCL 或 Allegro 进程的 ID。

Common Lisp 规范中没有任何内容可以实现这一点。进程 ID 过于依赖于实现。

在 SBCL 中,SB-POSIX包为大多数 POSIX 系统调用提供了 Lisp 接口,因此您将使用(sb-posix:getpid)

在 Allegro CL 中,操作系统接口功能位于EXCL.OSI包中,因此您可以使用(excl.ose:getpid)

有一种(基本上(可移植的方法可以做到这一点。CL 提供读取文件,可以观察到当前进程的 pid 是/proc/self/status的(也是/proc/self进程 pid 的符号链接,但我认为没有可移植的读取链接(。

具体来说,/proc/self/status是一个文本文件,包含如下所示的行:

Pid: 439

因此,您可以解析文件以提取它。

但是一旦你有了pid,如果没有系统调用或/proc怪异,你就无能为力了。

最终解决方案(大部分由@Dan罗伯逊和@coredump - 谢谢你们!

实际上@Dan罗伯逊给出了完整的答案——回想起来,我意识到。 这个答案只是他所说的实施。所以给他积分!

(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.

正如@Don Robertson指出的那样,文件/proc/self/status显示了打开它的"PID"编号的程序(每个程序对它的查看方式不同(。谢谢Don,因为这解决了真正找到程序的PID的问题(如果几个Lisp程序在机器上独立运行,shell中的pidof sbcl会给出几个数字。 调用外部程序已经过时了,如果我们打开这个文件,那么从 cl 中,就像@coredump指出的那样。

其他程序的PID编号

;; 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

最新更新