我想使用 elisp 执行特权命令,然后在看到特定输出时使用过滤器做进一步处理。
根据我的理解,在详尽的 RTFM 之后,我可以:
- 将
default-directory
设置为以“/sudo::/”开头的路径。 - 调用
start-file-process
启动将在 sudo 下运行的进程。
这是我写的一个试图做到这一点的函数:
(defun start-vpn (config-file password-file callback)
"Starts the VPN connection, waits for a DHCP address,
then invokes callback with the address it got."
(let* ((default-directory "/sudo::/tmp")
(buff (get-buffer-create "*openvpn*"))
(proc (start-file-process "openvpn" "*openvpn*"
"/usr/local/sbin/openvpn"
(concat "--config " config-file)
(concat "--auth-user-pass " password-file))))
(set-process-filter proc
(lambda (proc output)
(message "Got output: " output)
(let ((ip (get-vpn-ip-address output)))
(when ip
(callback ip)))))))
当我运行它时,我在 *Messages*
缓冲区中看到以下输出:
start-vpn
Tramp: Opening connection for root@localhost using sudo...
Tramp: Sending command `exec sudo -u root -s -H -p Password:'
Tramp: Waiting for prompts from remote shell
Tramp: Sending command `exec sudo -u root -s -H -p Password:'
Tramp: Found remote shell prompt on `localhost'
Tramp: Opening connection for root@localhost using sudo...done
(lambda (proc output) (message "Got output: " output) (let ((ip ...)) (if ip (progn ...))))
Got output:
...并且函数创建的 *openvpn*
缓冲区中没有输出。
我不是 elisp 专家,所以我怀疑我犯了一些愚蠢的错误。我对 *Messages*
缓冲区中的 "(lambda (proc ..."
也很好奇。
感谢任何建议、批评或提示。谢谢!
最佳答案
首先,在消息缓冲区中看到(lambda ...
的原因是set-process-filter
返回了过滤函数,因此start-vpn
也是。
您的消息
调用需要包含格式说明符才能实际显示输出:
(message "Got output: %s" output)
(callback ip)
将无法工作,原因有二:
- Emacs Lisp 对函数和变量有单独的命名空间,所以
(callback ip)
将调用 functioncallback
(不存在),而您需要(funcall callback ip)
来调用存储在变量callback
中的函数。 一旦你超过了那个,因为 Emacs Lisp 默认使用动态作用域,当你的 lambda 函数被调用时,
callback
的绑定(bind)已经消失了。在 Emacs 24 中,您可以将
lexical-binding
设置为t
,上面的代码应该可以工作。在任何情况下,您都可以显式使用lexical-let
宏:(lexical-let ((callback callback)) (lambda (proc output) (message "Got output: " output) (let ((ip (get-vpn-ip-address output))) (when ip (funcall callback ip))))
这个宏使用黑魔法在 lambda 函数中保留
callback
的值。
关于emacs - 如何在elisp中使用过滤器执行sudo命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16612529/