从 SBCL Common Lisp 中执行 'docker run'
Execute 'docker run' from within SBCL Common Lisp
我正在尝试 运行 我的 lisp 程序中的一个函数。它是一个连接到 IRC 频道的机器人,您可以使用特殊命令查询机器人以评估简单的 lisp 命令。因为从互联网上的人那里执行任意代码是极其危险的,所以我希望实际评估发生在虚拟机中,该虚拟机 运行 对机器人获得的每个评估查询执行 docker。
我的函数如下所示:
(defun run-command (cmd)
(uiop:run-program (list "docker" "run" "--rm" "-it" "my/docker" "sbcl" "--noinform" "--no-sysinit" "--no-userinit" "--noprint" "--disable-debugger" "--eval" (string-trim '(#\^M) (format nil "~A" cmd))) "--eval" "'(quit)'") :output '(:string :stripped t))
这个函数背后的想法是启动一个包含 SBCL 的 docker,运行 通过 SBCL --eval 命令并将其打印到 docker std-out。这个打印的字符串应该是 run-command
.
的结果
如果我打电话
docker run --rm -it my/docker sbcl --noinform --no-sysinit --no-userinit --noprint --disable-debugger --eval "(print (+ 2 3))" --eval "(quit)"
在我的命令行上,结果我只得到 5,这正是我想要的。
但是如果我 运行 在 lisp 中使用相同的命令,使用 uiop:run-program
函数我得到
Subprocess #<UIOP/LAUNCH-PROGRAM::PROCESS-INFO {1004FC3923}>
with command ("docker" "run" "--rm" "-it"
"my/docker" "sbcl" "--noinform"
"--no-sysinit" "--no-userinit" "--noprint"
"--disable-debugger" "--eval" "(+ 2 3)")
作为错误消息,这意味着该过程因某种原因失败。但我不知道这里到底出了什么问题。如果我只是执行例如“ls”,我会得到输出,所以该函数似乎可以正常工作。
我需要一些关于 uiop:run-program
的特殊知识还是我做错了什么?
提前致谢。
编辑:原来是 -it 标志引起了问题。删除标志后出现新错误。现在机器人没有执行权限docker。有没有办法在不授予它 sudo 权限的情况下授予它权限?
这里(或 SBCL)调用 docker 的方式可能有问题。要获取错误消息,请使用 :error-output :string
参数调用 uiop:run-program
,然后选择 continue
重新启动以实际上终止执行并打印错误输出(如果您是 运行 来自 SLIME 或其他 REPL)。如果您在非交互式环境中调用它,您可以将调用包装在处理程序绑定中:
(handler-bind ((uiop/run-program:subprocess-error
(lambda (e) (invoke-restart (find-restart 'continue)))))
(run-command ...))
原来是 -it
惹了麻烦。删除它并提升对机器人的正确权限后,一切正常。
我正在尝试 运行 我的 lisp 程序中的一个函数。它是一个连接到 IRC 频道的机器人,您可以使用特殊命令查询机器人以评估简单的 lisp 命令。因为从互联网上的人那里执行任意代码是极其危险的,所以我希望实际评估发生在虚拟机中,该虚拟机 运行 对机器人获得的每个评估查询执行 docker。
我的函数如下所示:
(defun run-command (cmd)
(uiop:run-program (list "docker" "run" "--rm" "-it" "my/docker" "sbcl" "--noinform" "--no-sysinit" "--no-userinit" "--noprint" "--disable-debugger" "--eval" (string-trim '(#\^M) (format nil "~A" cmd))) "--eval" "'(quit)'") :output '(:string :stripped t))
这个函数背后的想法是启动一个包含 SBCL 的 docker,运行 通过 SBCL --eval 命令并将其打印到 docker std-out。这个打印的字符串应该是 run-command
.
如果我打电话
docker run --rm -it my/docker sbcl --noinform --no-sysinit --no-userinit --noprint --disable-debugger --eval "(print (+ 2 3))" --eval "(quit)"
在我的命令行上,结果我只得到 5,这正是我想要的。
但是如果我 运行 在 lisp 中使用相同的命令,使用 uiop:run-program
函数我得到
Subprocess #<UIOP/LAUNCH-PROGRAM::PROCESS-INFO {1004FC3923}>
with command ("docker" "run" "--rm" "-it"
"my/docker" "sbcl" "--noinform"
"--no-sysinit" "--no-userinit" "--noprint"
"--disable-debugger" "--eval" "(+ 2 3)")
作为错误消息,这意味着该过程因某种原因失败。但我不知道这里到底出了什么问题。如果我只是执行例如“ls”,我会得到输出,所以该函数似乎可以正常工作。
我需要一些关于 uiop:run-program
的特殊知识还是我做错了什么?
提前致谢。
编辑:原来是 -it 标志引起了问题。删除标志后出现新错误。现在机器人没有执行权限docker。有没有办法在不授予它 sudo 权限的情况下授予它权限?
这里(或 SBCL)调用 docker 的方式可能有问题。要获取错误消息,请使用 :error-output :string
参数调用 uiop:run-program
,然后选择 continue
重新启动以实际上终止执行并打印错误输出(如果您是 运行 来自 SLIME 或其他 REPL)。如果您在非交互式环境中调用它,您可以将调用包装在处理程序绑定中:
(handler-bind ((uiop/run-program:subprocess-error
(lambda (e) (invoke-restart (find-restart 'continue)))))
(run-command ...))
原来是 -it
惹了麻烦。删除它并提升对机器人的正确权限后,一切正常。