Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/amazon-web-services/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Amazon web services 部署公共LispWeb应用程序_Amazon Web Services_Amazon Ec2_Lisp_Common Lisp_Hunchentoot - Fatal编程技术网

Amazon web services 部署公共LispWeb应用程序

Amazon web services 部署公共LispWeb应用程序,amazon-web-services,amazon-ec2,lisp,common-lisp,hunchentoot,Amazon Web Services,Amazon Ec2,Lisp,Common Lisp,Hunchentoot,我想知道如何部署用Hunchentoot、Wookie、Woo甚至Clack编写的公共LispWeb应用程序 也就是说,假设我编写了一个包含一些文件、包等的应用程序。通常,当我在本地工作时,我只需在REPL中运行一个命令,启动服务器,然后使用localhost:8000或类似的方式访问它 然而,对于将应用程序部署到生产服务器(如AWS EC2)的过程,我有点困惑。我应该以什么形式部署Lisp代码?有不同的选择吗?如果服务器需要重新启动或遇到问题,会发生什么情况 要在生产环境中运行lisp映像,可

我想知道如何部署用Hunchentoot、Wookie、Woo甚至Clack编写的公共LispWeb应用程序

也就是说,假设我编写了一个包含一些文件、包等的应用程序。通常,当我在本地工作时,我只需在REPL中运行一个命令,启动服务器,然后使用
localhost:8000
或类似的方式访问它


然而,对于将应用程序部署到生产服务器(如AWS EC2)的过程,我有点困惑。我应该以什么形式部署Lisp代码?有不同的选择吗?如果服务器需要重新启动或遇到问题,会发生什么情况

要在生产环境中运行lisp映像,可以使用以下命令从lisp代码生成fasl文件:

(compile-file "app.lisp")
通过调用sbcl运行生成的.fas文件

sbcl --noinform \
     --load app.fas \
     --eval "(defun main (argv) (declare (ignore argv)) (hunchentoot:start (make-instance 'hunchentoot:easy-acceptor :port 4242)))"

我发现了一个博客,其中有一个解决方案,我已经根据自己的需要对linux机器上的生产系统进行了调整。不幸的是,我再也找不到该博客的参考资料了,所以我可以向您展示我的解决方案,它是针对CCL的(而最初的解决方案是针对SBCL的),我对它更为熟悉。以下是启动系统的程序:

(require 'swank)
(require 'hunchentoot)

(defparameter *httpd-port* 9090)     ; The port Hunchentoot will be listening on
(defparameter *shutdown-port* 6700)  ; The port CCL will be listening for shutdown
                                     ; this port is the same used in /etc/init.d/hunchentoot
(defparameter *swank-port* 5016)     ; The port used for remote interaction with slime

;; Start the Swank server
(defparameter *swank-server*
  (swank:create-server :port *swank-port* :dont-close t))

(require 'YOUR-PACKAGE)
(YOUR-PACKAGE:YOUR-STARTING-FUNCTION)

(princ "Hunchentoot started on port ")
(princ *httpd-port*)
(terpri)

(let* ((socket (make-socket :connect :passive :local-host "127.0.0.1" :local-port *shutdown-port* :reuse-address t))
       (stream (accept-connection socket)))
  (close stream)
  (close socket))

(print "Stopping Hunchentoot...")
(YOUR-PACKAGE:YOUR-STOPPING-FUNCTION)

(dolist (proc (all-processes))
  (unless (equal proc *current-process*)
    (process-kill proc)))
(sleep 1)
(quit)
(dolist (thread (sb-thread:list-all-threads))
  (unless (equal sb-thread:*current-thread* thread)
    (sb-thread:terminate-thread thread)))
(sleep 1)
(sb-ext:quit)
其思想是,通过指定swank使用的端口,您可以使用slime连接到正在运行的系统。例如,我曾多次使用它动态地更改数据库链接,这种可能性的威力给我留下了深刻的印象

运行中的系统可通过以下方式终止:

telnet 127.0.0.1 6700
并由以下内容发起:

nohup ccl -l initcclserver.lisp >& server.out &
在以前版本的脚本中,我找到了SBCL特定的部分,因此如果使用它,可以修改脚本

要接受终止连接,请执行以下操作:

(sb-bsd-sockets:socket-bind socket #(127 0 0 1) *shutdown-port*)
(sb-bsd-sockets:socket-listen socket 1)
(multiple-value-bind (client-socket addr port)
  (sb-bsd-sockets:socket-accept socket)
(sb-bsd-sockets:socket-close client-socket)
(sb-bsd-sockets:socket-close socket)))
要关闭系统,请执行以下操作:

(require 'swank)
(require 'hunchentoot)

(defparameter *httpd-port* 9090)     ; The port Hunchentoot will be listening on
(defparameter *shutdown-port* 6700)  ; The port CCL will be listening for shutdown
                                     ; this port is the same used in /etc/init.d/hunchentoot
(defparameter *swank-port* 5016)     ; The port used for remote interaction with slime

;; Start the Swank server
(defparameter *swank-server*
  (swank:create-server :port *swank-port* :dont-close t))

(require 'YOUR-PACKAGE)
(YOUR-PACKAGE:YOUR-STARTING-FUNCTION)

(princ "Hunchentoot started on port ")
(princ *httpd-port*)
(terpri)

(let* ((socket (make-socket :connect :passive :local-host "127.0.0.1" :local-port *shutdown-port* :reuse-address t))
       (stream (accept-connection socket)))
  (close stream)
  (close socket))

(print "Stopping Hunchentoot...")
(YOUR-PACKAGE:YOUR-STOPPING-FUNCTION)

(dolist (proc (all-processes))
  (unless (equal proc *current-process*)
    (process-kill proc)))
(sleep 1)
(quit)
(dolist (thread (sb-thread:list-all-threads))
  (unless (equal sb-thread:*current-thread* thread)
    (sb-thread:terminate-thread thread)))
(sleep 1)
(sb-ext:quit)

希望这能有所帮助。

最近,我通过为web应用程序构建自包含的可执行文件找到了一些方法,我在(发布和部署部分)以及上的构建部分写了相关内容

我把有趣的部分复制到这里,每个资源都有更多的内容。欢迎编辑,主要是那些资源,谢谢

编辑2019年7月:我在食谱上贡献了一页:

编辑:另请参见提供专业CL支持的工具和平台列表:

(已编辑)如何将web应用程序作为脚本运行 下面我将解释如何构建和运行可执行文件,但我们当然可以将应用程序作为脚本运行。在lisp文件中,说
run.lisp
,确保:

  • 要加载项目的asd文件,请执行以下操作:
    (加载“my project.asd”)
  • 要加载其依赖项:
    (ql:quickload:myproject)
  • 调用其主要功能:
    (我的项目:start)
    (给定的
    start
    是一个导出符号,否则
    ::start
这样,应用程序启动并返回一个Lisp REPL。您可以与正在运行的应用程序交互。您可以在运行时更新它,甚至安装新的Quicklisp库

如何构建自包含的可执行文件 有关自制软件包和Debian软件包的绑定,请参见

与SBCL 如何构建(自包含的)可执行文件是特定于实现的(请参见 下面是Buildapp和Rowsell)。如前所述,使用SBCL , 这是一个问题:

(sb ext:save lisp and die#P“可执行文件的路径/名称”:toplevel#'my-app:main function:executable t)
sbext
是用于运行外部进程的SBCL扩展。见其他 (其中许多都可以在其他库中移植)

:可执行文件t
告诉您构建可执行文件而不是 形象。我们可以建立一个图像来保存当前状态 Lisp图像,稍后再使用它。特别有用,如果 我们做了很多计算密集型的工作

如果您尝试在Slime中运行此操作,您将得到一个关于线程运行的错误:

无法保存运行多个线程的core

从简单的SBCL repl运行该命令

我想您的项目具有Quicklisp依赖项。然后你必须:

  • 确保在Lisp启动时安装并加载Quicklisp(您可以 已完成Quicklisp安装)
  • 加载项目的.asd
  • 安装依赖项
  • 构建可执行文件
这就产生了:

(load "my-app.asd")
(ql:quickload :my-app)
(sb-ext:save-lisp-and-die #p"my-app-binary" :toplevel #'my-app:main :executable t)
从命令行或生成文件中,使用
--load
--eval

build:
    sbcl --non-interactive \
         --load my-app.asd \
         --eval '(ql:quickload :my-app)' \
         --eval "(sb-ext:save-lisp-and-die #p\"my-app\" :toplevel #my-app:main :executable t)"
使用ASDF 现在我们已经了解了基本知识,我们需要一个可移植的方法。因为 版本3.1,ASDF允许这样做。它介绍了, 从.asd中读取参数的。将此添加到.asd声明中:

:build-operation "program-op" ;; leave as is
:build-pathname "<binary-name>"
:entry-point "<my-system:main-function>"
使用Roswell或Buildapp ,一位实施经理,还有很多 此外,还有
rosbuild
命令,该命令应该适用于许多应用程序 实现

我们还可以通过
ros安装我的应用程序
,让我们的应用程序可以通过Roswell安装。见其文件

我们将以一句话结束 这是一场经过考验的战斗 仍然流行的“SBCL或CCL应用程序”,用于配置和保存 一个可执行的公共Lisp图像”

许多应用程序都使用它(例如, ),可于 Debian:
apt安装buildapp
,但现在asdf:make或Roswell不需要它

用于web应用程序 我们同样可以为我们的web应用程序构建一个自包含的可执行文件。信息技术 因此将包含一个web服务器,并能够在 命令行:

$ ./my-web-app
Hunchentoot server is started.
Listening on localhost:9003.
请注意,这将运行生产Web服务器,而不是开发Web服务器, 因此,我们可以立即在VPS上运行二进制文件,并从 外面

我们有一件事要处理,那就是找到并放置 前台正在运行的web服务器。在我们的
main
函数中,我们 可以这样做:

(defun main ()
  (start-app :port 9003) ;; our start-app, for example clack:clack-up
  ;; let the webserver run.
  ;; warning: hardcoded "hunchentoot".
  (handler-case (bt:join-thread (find-if (lambda (th)
                                            (search "hunchentoot" (bt:thread-name th)))
                                         (bt:all-threads)))
    ;; Catch a user's C-c
    (#+sbcl sb-sys:interactive-interrupt
      #+ccl  ccl:interrupt-signal-condition
      #+clisp system::simple-interrupt-condition
      #+ecl ext:interactive-interrupt
      #+allegro excl:interrupt-signal
      () (progn
           (format *error-output* "Aborting.~&")
           (clack:stop *server*)
           (uiop:quit)))
    (error (c) (format t "Woops, an unknown error occured:~&~a~&" c))))
我们使用了
波尔多线程库(
(ql:quickload“波尔多线程”)
,别名
bt
)和
uiop
,这是ASDF so的一部分 已加载,以便以便携方式退出(
uiop:quit
,使用 选择权
sudo systemctl start my-app.service
systemctl status my-app.service
journalctl -f -u my-app.service
Restart=always
[Install]
WantedBy=basic.target
sudo systemctl enable my-app.service
mmap: wanted 1040384 bytes at 0x20000000, actually mapped at 0x715fa2145000
ensure_space: failed to allocate 1040384 bytes at 0x20000000
(hint: Try "ulimit -a"; maybe you should increase memory limits.)
sudo bash -c "echo 0 > /proc/sys/kernel/randomize_va_space"
;; a little common lisp swank demo
;; while this program is running, you can connect to it from another terminal or machine
;; and change the definition of doprint to print something else out!
;; (ql:quickload :swank)
;; (ql:quickload :bordeaux-threads)

(require :swank)
(require :bordeaux-threads)

(defparameter *counter* 0)

(defun dostuff ()
  (format t "hello world ~a!~%" *counter*))

(defun runner ()
  (bt:make-thread (lambda ()
                    (swank:create-server :port 4006)))
  (format t "we are past go!~%")
  (loop while t do
       (sleep 5)
       (dostuff)
       (incf *counter*)
       ))

(runner)
sbcl --load demo.lisp
ssh -L4006:127.0.0.1:4006 username@example.com
(defun dostuff ()
  (format t "goodbye world ~a!~%" *counter*))
(setf *counter* 0)