Сначала цитата - вдруг кто-то не знает об этом замечательном инциденте.

<blockquote><i> И даже более впечатляющий пример удаленной отладки произошел в миссии NASA «Deep Space 1» в 1998 году. Через полгода после запуска космического корабля, небольшой код на Lisp должен был управлять космическим кораблем в течении двух дней для проведения серии экспериментов. Однако, неуловимое состояние гонки (race condition) в коде не было выявлено при тестировании на земле и было обнаружено уже в космосе. Когда ошибка была выявлена в космосе (100 миллионов миль от Земли) команда смогла произвести диагностику и исправление работающего кода, что позволило завершить эксперимент. Один из программистов сказал об этом следующее:

— Отладка программы, работающей на оборудовании стоимостью 100 миллионов долларов, которая находится в 100 миллионах миль от вас, является интересным опытом. REPL, работающий на космическом корабле, предоставляет бесценные возможности в нахождении и устранении проблем. </i></blockquote>

Лично я, смелый и храбрый программист могу только позавидовать такому экстремальному времяпрепровождению. И естественно, сразу как только я это прочел - мне захотелось попробовать так же :) Оказалось это довольно легко и может считаться штатной возможностью, которую следует юзать и в хвост и в гриву на боевых серваках (если конечно вы достаточно оптимистичны, самоуверенны и безрассудны :)

Я и не знал, что многие этого не знают, а те кто знают - забывают рассказать. Это как секс - после того как первый раз сделаешь это - начинаешь делать все на автомате, не задумываясь :)

Шаг за шагом

  1. Заходим на сервак по ssh:

<code>ssh user@host.ru</code>

Спрашивают пароль, вводить нужно правильный, иначе странным образом ничего не получается.

  1. Запускаем screen. По какой-то магической причине, если пропустить этот шаг, то после того как терминальная сессия закроется вся магия исчезнет.
  2. Внутри screen запускаем sbcl. Тут сразу дают REPL, но весь дзен будет дальше, поэтому…
  3. Вводим в REPL следующий код (можно скопировать прямо отсюда, вреда не будет, я гарантирую это!)

<source code="lisp"> (require 'asdf) (asdf:oos 'asdf:load-op 'swank) (setq swank:*use-dedicated-output-stream* nil) (swank:create-server :coding-system "utf-8-unix" :dont-close t :port 4005) </source>

Этот код запустить swank внутри sbcl и он (swank) начнет слушать 4005 порт, но будет делать это на удаленной машине - ну а мы там и находимся пока внутри терминальной сессии.

  1. Нажимаем <code>Ctrl+a d</code> - чтобы выйти из screen без его закрытия, оставив под screen`ом работающий sbcl с запущенным в нем swank`ом. Больше нам нечего делать в терминальной сессии, поэтому можно нажать <code>Ctrl+d</code> чтобы из нее выйти. Теперь мы снова у себя на машине.
  2. Открываем ssh-тоннель на удаленную машину:

<code>ssh -2 -N -f -L 4005:localhost:4005 user@host.ru</code>

Теперь все обращения к нашему 4005 порту будут уходить на удаленную машину и обращаться там по 4005 порту - а нам это и надо

  1. Заходим в emacs и набираем <code>M-x slime-connect</code> - и емакс послушно коннектится на локальный 4005 порт, который форвардится на удаленный 4005 порт, где его принимает swank, после чего вы можете наслаждаться мощью лиспа ни в чем себе не отказывая.

Что может быть полезным

  1. swank сам по себе - это библиотка лиспа. Она может быть неустановлена. Установиить можно например с помощью asdf-install:

<source code="lisp"> (require 'asdf-install) (asdf-install:install 'swank) </source>

Но лучше бы вам знать, как устанавливать библиотки в лиспе вручную. Все просто - нужно слить библиотеку, положить ее в нужную папку (у меня это usr/lib/sbcl/site) и сделать симлинк на asd-файл в папке систем (у меня это usr/lib/sbcl/site-systems). Нужные папки легко найти по команде locate site-systems - там оно все рядом. Альтернативный вариант поиска, если вы знаете какую-нибудь из установленных библиотек, например, alexandria - это выполнить в REPL такой код:

<code>(asdf:component-pathname (asdf:find-system '#:alexandria))</code>

  1. версия swank (снапшот) должна быть идентична и на клиенте и на сервере. Если об этом забыть можно словить прикольные глюки :)
  2. Если, когда вы отошли хакнуть что-нибудь другое или просто попить кофе, ssh-тоннель умирает от безделья и вам приходится с матом поднимать его снова, то пропишите в /etc/ssh/sshconfig директиву <code>ServerAliveInterval 5</code>
  3. Некоторые лисперы забывают сконфигурировать emacs :) В вашем инициализационном файле емакса должно быть что-то похожее на это:

<source code="elisp"> ;; Lisp (SLIME) interaction (setq inferior-lisp-program "sbcl" lisp-indent-function 'common-lisp-indent-function slime-complete-symbol-function 'slime-fuzzy-complete-symbol ; common-lisp-hyperspec-root "file:///Users/lisp/HyperSpec" slime-startup-animation nil) ;; SLIME (add-to-list 'load-path "~/.emacs.d/slime") (require 'slime) ;(set-language-environment "utf-8") (setq slime-net-coding-system 'utf-8-unix) (slime-setup '(slime-fancy)) </source>

Happy hacking!