Ответ 1
В последнее время я кое-что выяснил, создав автономные исполняемые файлы для веб-приложений, и написал об этом в lisp-trip/web-dev (разделы по доставке и развертыванию), а также в части по сборке в Common Lisp Cookbook/scripting # для веб-приложений.
Я копирую интересные части здесь, там немного больше на каждом ресурсе. Редактирование приветствуется, прежде всего на этих ресурсах, спасибо!
изменить июль 2019 г. Я добавил страницу в кулинарную книгу: https://lispcookbook.github.io/cl-cookbook/web.html
изменить: см. также список инструментов и платформ, которые предоставляют профессиональную поддержку CL: https://github.com/CodyReichert/awesome-cl#deployment
Как создать автономный исполняемый файл
Смотрите также https://github.com/CodyReichert/awesome-cl#interfaces-to-other-package-managers о привязках к пакетам Homebrew и Debian.
С SBCL
Как создавать (автономные) исполняемые файлы зависит от реализации (см. ниже Buildapp и Rowsell). С SBCL, как говорит его документация, это вопрос:
(sb-ext:save-lisp-and-die #P"path/name-of-executable" :toplevel #'my-app:main-function :executable t)
sb-ext
является расширением SBCL для запуска внешних процессов. См другие
SBCL расширения
(многие из них сделаны переносимыми для реализации в других библиотеках).
:executable t
говорит, что нужно создать исполняемый файл вместо
образ. Мы могли бы создать изображение, чтобы сохранить состояние нашего текущего
Lisp, чтобы вернуться к работе позже. Особенно полезно, если
мы проделали большую работу, требующую больших вычислительных ресурсов.
Если вы попытаетесь запустить это в Slime, вы получите сообщение об ошибке:
Невозможно сохранить ядро с несколькими запущенными потоками.
Запустите команду из простой реплики SBCL.
Я полагаю, у вашего проекта есть зависимости Quicklisp. Вы должны тогда:
- убедитесь, что Quicklisp установлен и загружен при запуске Lisp (вы завершена установка Quicklisp)
load
проект .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)
Из командной строки или из Makefile используйте --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 позволяет это сделать. Он вводит команду make
,
который читает параметры из .asd. Добавьте это в вашу декларацию .asd:
:build-operation "program-op" ;; leave as is
:build-pathname "<binary-name>"
:entry-point "<my-system:main-function>"
и позвоните в asdf:make :my-system
.
Итак, в Makefile:
LISP ?= sbcl
build:
$(LISP) --non-interactive \
--load my-app.asd \
--eval '(ql:quickload :my-app)' \
--eval '(asdf:make :my-system)'
с Roswell или Buildapp
Розуэлл, менеджер по внедрению и многое другое
более того, также есть команда ros build
, которая должна работать для многих
Реализации.
Мы также можем сделать наше приложение устанавливаемым с помощью Roswell ros install
my-app
. Смотрите документацию.
Мы закончим с словом на Buildapp, проверенный в бою и по-прежнему популярное приложение для SBCL или CCL, которое настраивает и сохраняет исполняемый образ Common Lisp ".
Многие приложения используют его (например,
pgloader), он доступен на
Debian: apt install buildapp
, но вам не нужно это сейчас с asdf: make или Roswell.
Для веб-приложений
Аналогичным образом мы можем создать автономный исполняемый файл для нашего веб-приложения. Это Таким образом, будет содержать веб-сервер и сможет работать на командная строка:
$ ./my-web-app
Hunchentoot server is started.
Listening on localhost:9003.
Обратите внимание, что здесь работает производственный веб-сервер, а не сервер разработки, так что мы можем сразу запустить двоичный файл на нашем VPS и получить доступ к приложению из снаружи.
У нас есть одна вещь, чтобы заботиться, это найти и положить нить
работающий веб-сервер на переднем плане. В нашей функции 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 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))))
Мы использовали библиотеку bordeaux-threads
((ql:quickload
"bordeaux-threads")
, псевдоним bt
) и uiop
, которая является частью ASDF, поэтому
уже загружен, чтобы выйти переносным способом (uiop:quit
, с
необязательный код возврата вместо sb-ext:quit
).
Разбор аргументов командной строки
см. Поваренную книгу.
развертыванияПросто с исполняемым файлом. Веб-приложение сразу видно снаружи.
На Heroku
Смотрите этот сборочный пакет.
Демонизация, перезапуск в случае сбоев, обработка журналов
Посмотрите, как это сделать в вашей системе.
Большинство дистрибутивов GNU/Linux теперь поставляются с Systemd.
Примеры поиска результата:
Это так же просто, как написать файл конфигурации:
# /etc/systemd/system/my-app.service
[Unit]
Description=stupid simple example
[Service]
WorkingDirectory=/path/to/your/app
ExecStart=/usr/local/bin/sthg sthg
Type=simple
Restart=always
RestartSec=10
запустив команду для его запуска:
sudo systemctl start my-app.service
команда для проверки ее статуса:
systemctl status my-app.service
и Systemd может обрабатывать ведение журнала (мы пишем в stdout или stderr, он записывает журналы):
journalctl -f -u my-app.service
и обрабатывает сбои, перезапускает приложение:
Restart=always
и он может запустить приложение после перезагрузки:
[Install]
WantedBy=basic.target
чтобы включить его:
sudo systemctl enable my-app.service
Ошибка отладки SBCL: sure_space: не удалось выделить n байтов
Если вы получили эту ошибку с SBCL на вашем сервере:
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.)
затем отключите ASLR:
sudo bash -c "echo 0 > /proc/sys/kernel/randomize_va_space"
Подключение к удаленному серверу Swank
Маленький пример здесь: http://cvberry.com/tech_writings/howtos/remotely_modifying_a_running_program_using_swank.html.
Он определяет простую функцию, которая печатает навсегда:
;; 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 [email protected]
это безопасно перенаправит порт 4006 на сервере на example.com Порт нашего локального компьютера 4006 (Swanks принимает подключения от локальный).
Мы подключаемся к бегущему Суонку с помощью M-x slime-connect
и набираем
порт 4006.
Мы можем написать новый код:
(defun dostuff ()
(format t "goodbye world ~a!~%" *counter*))
(setf *counter* 0)
и оцените его, как обычно, с M-x slime-eval-region
, например. Выход должен измениться.
На странице CV Berry больше указателей.
Горячая перезагрузка
Пример с Quickutil. Смотрите заметки о путешествии.
Это должно быть выполнено на сервере (простая команда fabfile может вызвать это
через сш). Предварительно fab update
запустил git pull
на
сервер, поэтому новый код присутствует, но не работает. Это подключается к
локальный сервер swank, загружает новый код, останавливает и запускает приложение в
строка.
Непрерывная интеграция, непрерывная доставка исполняемых файлов, Docker
Видеть https://lispcookbook.github.io/cl-cookbook/testing.html#continuous-integration