shebangスクリプトを書く

ゆっくりSBCLのマニュアル読んでいって, その過程をメモして行こうと思う.
まあ, この記事だけで終わる可能性大だけどwww
今日は, マニュアルの2.1.3, 2.4.2, 2.4.4.1の3つをざっと読んでみた.



shebang(シェバング)というのは, よくPerlとかシェルスクリプトのファイルで1行目に書いてあるもの.
シェルスクリプトの例だとこんな感じ. この例だと「#!/bin/sh」がshebang.
ファイル名は, test.shで. まあ別に何でもいいけど.

#!/bin/sh

echo "Hello, World!"

あとは, こいつに実行権限を与えてあげる.

$ chmod u+x test.sh

すると, 「$ sh test.sh」と実行しなくても, 「$ ./test.sh」で実行できるようになる.


それで本題だけど, SBCLは, マニュアルの2.1.3項によるとデフォルトだとこのshebangをサポートしてないらしい.
とりあえず, こんなの書いて実行してみる.

#!/usr/local/bin/sbcl

;; Hello, World
(write-line "Hello, World!")

これに実行権限を加えて, 実行した結果がこれ.

$ ./sbcl-shebang-test.lisp
This is SBCL 1.0, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
*

普通にSBCLが立ち上がるだけで, 実行できていない.



これを解決するには, SBCLに設定を追加してやると良いとのこと.
マニュアルの2.4.4.1項より.
$HOME/.sbclrcに次の内容を追記する.

;;; If the first user-processable command-line argument is a filename,
;;; disable the debugger, load the file handling shebang-line and quit.
(let ((script (and (second *posix-argv*)
                   (probe-file (second *posix-argv*)))))
   (when script
      ;; Handle shebang-line
      (set-dispatch-macro-character #\# #\!
                                    (lambda (stream char arg)
                                       (declare (ignore char arg))
                                       (read-line stream)))
      ;; Disable debugger
      (setf *invoke-debugger-hook*
            (lambda (condition hook)
              (declare (ignore hook))
              ;; Uncomment to get backtraces on errors
              ;; (sb-debug:backtrace 20)
              (format *error-output* "Error: ~A~%" condition)
              (quit)))
      (load script)
      (quit)))

そして, shebangを次のようにする.

#!/usr/local/bin/sbcl --noinform

書き換えたファイルは, こんな感じ.

#!/usr/local/bin/sbcl --noinform

;; Hello, World
(write-line "Hello, World!")

こいつに実行権限を与えて, 実行してみる.

$ ./sbcl-shebang-test.lisp
Hello, World!

問題なく, 実行できている.
ちなみに, write-lineでなく, printを使ってみたら,
何かよくわからないけど, 「Hello, World!」の後に文字化けのようなものが表示された.
関数printは使わないで, write-lineを使った方が良いってことなのかなあ.

追記

あっ, 分かった.
最後に改行が無いのが原因だ.
でも, print関数で最後に改行を出力する方法が分からない. どうすんだろう?

さらに追記

うーん, こうやるものなのかなあ. 一応できたけど・・・.

(format t "Hello, World~%")

やっぱり, printは使わないものなのかなあ.

さらにさらに追記

どうやら、sbclの1.0.22以降であれば、.sbclrcに設定を書く必要が無いっぽ。
スクリプトの先頭を以下のようにすれば良いみたい。

#!/usr/local/bin/sbcl --script