プログラミング環境としてNetBSDを使う話
昨日の記事では、NetBSDにsshログインするまでの手順を書いてみました。今日はこの環境をプログラミングのために活用する内容で記事を書いてみようとおもいます。
C言語でプログラミングする
NetBSDのインストール時に"Compiler Tools"という配布セットを選択すると、gccによる開発環境がインストールされます。
(一昨日のインストール手順は"Compiler Tools"を選択しています)
というワケで、C言語であれば、かなりお手軽にプログラミング環境ができあがります。
シェルスクリプト
これも最初から利用できます、というよりもUNIX系OSであれば、どこでも利用できますね。bashやzshは後述するパッケージやpkgsrcでインストールします。
$ ls /bin/*sh
/bin/csh /bin/ksh /bin/sh
パッケージで色々な言語をインストールして使う
パッケージを検索...。
NetBSDもFreeBSDやOpenBSDやSolaris、Linuなんとか等のUNIX系OSと同じく、パッケージで様々なプログラミグ言語を利用できます。
が、残念なことにNetBSDのpkg_addではパッケージ名の検索ができません...。
(私の知識が無いだけで、検索用のコマンドやオプションは存在するかもしれません)
とはいえ、そこはUNIX系OS。上手いことサクッとパッケージ名を検索できるようにしてしまいましょう。
環境変数PKG_PATHにはパッケージが置かれているURLが入っているので、単にそこからHTMLをダウンロードして、grepで検索するだけでOKです(エレガントさは皆無ですが...)
$ sudo -i pkg_add w3m
$ w3m -dump ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/amd64/6.0/All > pkg_list.txt
$ head -n10 pkg_list.txt
Index of ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/amd64/6.0/All/
[Upper Directory]
.pkgcache . . . . . . . . . . . . . . . . . . . . . . . Dec 3 08:20 31.6M
0verkill-0.16nb1.tgz. . . . . . . . . . . . . . . . . . Nov 16 10:20 299K
2vcard-0.5nb3.tgz . . . . . . . . . . . . . . . . . . . Nov 15 21:59 9.51K
3ddesktop-0.2.9nb12.tgz . . . . . . . . . . . . . . . . Nov 17 17:58 82.4K
3proxy-0.5.3.11nb1.tgz. . . . . . . . . . . . . . . . . Nov 26 13:05 70.6K
4stAttack-2.1.4nb17.tgz . . . . . . . . . . . . . . . . Nov 27 13:15 1.80M
6tunnel-0.11rc2.tgz . . . . . . . . . . . . . . . . . . Nov 17 02:47 11.3K
こんな感じでパッケージを検索します。
$ grep ^nodejs pkg_list.txt
nodejs-0.10.32.tgz. . . . . . . . . . . . . . . . . . . Nov 16 21:09 4.28M
パッケージ関連コマンドの簡単な使い方
パッケージの追加
すでにコマンドの実行例で示していますが、パッケージをインストールする場合はpkg_addコマンドを使用します。
$ sudo -i pkg_add -v w3m
pkg_infoコマンドでインストールされているパッケージ名の一覧を取得できます。
$ pkg_info -a | head -n10
sudo-1.7.10p8 Allow others to run commands as root
readline-6.3nb3 GNU library that can recall and edit previous input
bash-2.05.2.9nb1 The GNU Bourne Again Shell (version 2)
perl-5.20.0nb2 Practical Extraction and Report Language
libatomic_ops-7.4.0nb1 Multi-platform library of atomic operations by Hans Boehm
boehm-gc-7.4.2 Garbage collection and memory leak detection for C and C++
w3m-0.5.3nb13 Multilingualized version of a pager/text-based browser w3m
libidn-1.29 Internationalized Domain Names command line tool
wget-1.16 Retrieve files from the 'net via HTTP and FTP
libyaml-0.1.6 YAML 1.1 parser and emitter written in C
特定のパッケージがインストールしたファイルを知りたい場合は、"pkg_info -L"とします。
$ pkg_info -L sudo
Information for sudo-1.7.10p8:
Files:
/usr/pkg/bin/sudo
/usr/pkg/bin/sudoedit
/usr/pkg/bin/sudoreplay
/usr/pkg/libexec/sudo_noexec.so
/usr/pkg/man/man5/sudoers.5
/usr/pkg/man/man8/sudo.8
/usr/pkg/man/man8/sudoedit.8
/usr/pkg/man/man8/sudoreplay.8
/usr/pkg/man/man8/visudo.8
/usr/pkg/sbin/visudo
/usr/pkg/share/doc/sudo/ChangeLog
/usr/pkg/share/doc/sudo/HISTORY
/usr/pkg/share/doc/sudo/LICENSE
/usr/pkg/share/doc/sudo/NEWS
/usr/pkg/share/doc/sudo/README
/usr/pkg/share/doc/sudo/TROUBLESHOOTING
/usr/pkg/share/doc/sudo/UPGRADE
/usr/pkg/share/doc/sudo/sample.pam
/usr/pkg/share/doc/sudo/sample.sudoers
/usr/pkg/share/doc/sudo/sample.syslog.conf
/usr/pkg/share/examples/sudo/sudoers
NetBSDでのアプリケーションインストール方法としては、コンパイル済みバイナリをインストールためのパッケージ(上記で説明している方法)と、ソースコードからアプリケーションをビルドして利用するpkgsrcという2つがあります。
pkgsrcについては、@ebijunさんが12/8のAdvent Calendarにてpkgsrcでソフトウェアをインストールするという記事を公開されていますのでぜひご覧ください。
いろいろプログラミング言語を試してみる
いろいろなプログラミング言語がパッケージで提供されているので、Hello,Worldならぬ四月は君の嘘プログラムで試してみます。
ruby
まずはruby。いくつかのバージョンが提供されていますね(EOLな1.8系があるのはたぶん目の錯覚...)
$ grep ^ruby pkg_list.txt | head -n4
ruby-1.8.7.374.tgz. . . . . . . . . . . . . . . . . . . Nov 22 21:18 1.57K
ruby-1.9.3p551.tgz. . . . . . . . . . . . . . . . . . . Nov 26 15:54 1.59K
ruby-2.0.0p598.tgz. . . . . . . . . . . . . . . . . . . Nov 26 15:28 1.58K
ruby-2.1.5.tgz. . . . . . . . . . . . . . . . . . . . . Nov 26 16:12 1.58K
ruby 2.1.5を試してみます。
$ sudo -i pkg_add -v ruby-2.1.5
$ ruby -e 'print "Your lie in April.\n"'
Your lie in April.
Lua
次にLuaですが、これはNetBSDの標準配布セットにluaコマンドが含まれており、パッケージでLuaをインストールすると2つのバージョンのluaが存在する形になります。
$ grep ^lua[0-9]*-[0-9] pkg_list.txt
lua51-5.1.5nb1.tgz. . . . . . . . . . . . . . . . . . . Nov 12 14:36 343K
lua52-5.2.3nb1.tgz. . . . . . . . . . . . . . . . . . . Nov 12 14:45 377K
Lua 5.2を試してみます。
$ sudo -i pkg_add -v lua52-5.2.3nb1
/usr/bin/luaと/usr/pkg/bin/lua5.2がありますね。
$ ls -li `which lua`
2435606 -r-xr-xr-x 1 root wheel 17592 Sep 29 16:37 /usr/bin/lua
$ ls -li `which lua5.2`
72197 -rwxr-xr-x 1 root wheel 15944 Nov 12 14:45 /usr/pkg/bin/lua5.2
/usr/bin/luaのバージョンは5.1.4です。
$ /usr/bin/lua -v
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
こんな感じで動きます。
$ echo 'print "Your lie in April."' | /usr/bin/lua -
Your lie in April.
$ echo 'print "Your lie in April."' | /usr/pkg/bin/lua5.2 -
Your lie in April.
python
(rubyと比べてパッケージが少ない気もしますが)Pythonも利用できます。
$ grep ^python pkg_list.txt
python26-2.6.9nb3.tgz . . . . . . . . . . . . . . . . . Nov 12 10:22 12.6M
python27-2.7.8nb1.tgz . . . . . . . . . . . . . . . . . Nov 12 08:12 14.8M
python33-3.3.5nb4.tgz . . . . . . . . . . . . . . . . . Nov 12 13:12 18.1M
python34-3.4.1nb1.tgz . . . . . . . . . . . . . . . . . Nov 12 12:59 20.4M
pythontidy-1.20nb1.tgz. . . . . . . . . . . . . . . . . Nov 16 06:21 26.2K
Pythonはバージョンがコマンドの末尾に付くので注意。
$ sudo -i pkg_add -v python34-3.4.1nb1
$ python3.4 --version
Python 3.4.1
$ python3.4 -c 'print("Your lie in April.")'
Your lie in April.
Java
NetBSDではOpenJDKなJavaが利用できます。
$ grep jdk pkg_list.txt
openjdk7-1.7.65.tgz . . . . . . . . . . . . . . . . . . Nov 19 19:30 66.4M
openjdk7-bin-20090502.tgz . . . . . . . . . . . . . . . Nov 24 22:32 55.2M
$ sudo -i pkg_add -v openjdk7-1.7.65
バージョンは1.7.0です。
$ openjdk7-java -version
openjdk version "1.7.0-internal"
OpenJDK Runtime Environment (build 1.7.0-internal-pkgsrc_2014_11_19_18_55-b00)
OpenJDK 64-Bit Server VM (build 24.65-b04, mixed mode)
インストールされるjava関連コマンドは頭に"openjdk7-"が付きます。
$ ls /usr/pkg/bin/openjdk7-*
/usr/pkg/bin/openjdk7-jar /usr/pkg/bin/openjdk7-orbd
/usr/pkg/bin/openjdk7-java /usr/pkg/bin/openjdk7-policytool
/usr/pkg/bin/openjdk7-javac /usr/pkg/bin/openjdk7-rmid
/usr/pkg/bin/openjdk7-javadoc /usr/pkg/bin/openjdk7-rmiregistry
/usr/pkg/bin/openjdk7-javah /usr/pkg/bin/openjdk7-servertool
/usr/pkg/bin/openjdk7-javap /usr/pkg/bin/openjdk7-tnameserv
/usr/pkg/bin/openjdk7-keytool
例えばElasticsearcとかだと、./bin/elasticsearchスクリプトから"java"というコマンド名でjarファイルを起動する(というか、普通javaコマンドですね)ので、javaという名前でopenjdk7-javaコマンドのシンボリックリンクを作成しておくと良いかもしれません。
PHP
PHPも複数のバージョンが提供されています。
$ grep ^php- pkg_list.txt | less
php-5.3.29nb1.tgz . . . . . . . . . . . . . . . . . . . Nov 12 15:25 4.43M
php-5.4.35.tgz. . . . . . . . . . . . . . . . . . . . . Nov 23 11:29 4.84M
php-5.5.19.tgz. . . . . . . . . . . . . . . . . . . . . Nov 23 11:47 5.01M
$ sudo -i pkg_add -v php-5.5.19
$ php --version
PHP 5.5.19 (cli) (built: Nov 23 2014 11:47:13)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
$ php -r 'print "Your lie in April\n";'
Your lie in April
JavaScript
JavaScriptの環境として、NodeJSが提供されています。
$ grep ^nodejs pkg_list.txt
nodejs-0.10.32.tgz. . . . . . . . . . . . . . . . . . . Nov 16 21:09 4.28M
$ sudo -i pkg_add -v nodejs
$ node --version
v0.10.32
$ node -e 'console.log("Your lie in April.");'
Your lie in April.
R
Rもある(Rだけに)。
$ grep ^R-[0-9] pkg_list.txt
R-3.1.1.tgz . . . . . . . . . . . . . . . . . . . . . . Nov 19 20:28 36.9M
$ sudo -i pkg_add -v R-3.1.1
$ R --version
R version 3.1.1 (2014-07-10) -- "Sock it to Me"
Copyright (C) 2014 The R Foundation for Statistical Computing
Platform: x86_64--netbsd (64-bit)
...
Rでも君嘘プログラム(初めてRのコードを書いた気がする)。
$ R
R version 3.1.1 (2014-07-10) -- "Sock it to Me"
Copyright (C) 2014 The R Foundation for Statistical Computing
Platform: x86_64--netbsd (64-bit)
...
> print("Your lie in April.")
[1] "Your lie in April."
NetBSDのプログラミング環境のもうひとつの楽しみ方
パッケージを使って様々なプログラミング言語を試してみるのも良いですが、NetBSDには、もうひとつの楽しみ方があります。
(楽しいと感じるかは個人差があります)
インストールされたNetBSDのコマンド群はシンボル情報が含まれており、objdump等で逆アセンブルした結果から元のソースコードを思い浮かべてみる、という楽しみ方です。
例えば、sleepコマンドを見てみます。
$ which sleep
/bin/sleep
$ file /bin/sleep
/bin/sleep: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for NetBSD 6.1.5, not stripped
objdump -dで逆アセンブルしてみます。main()の開始直後のあたりを眺めてみます。
$ objdump -d /bin/sleep
...
0000000000400df9 <main>:
400df9: 55 push %rbp
400dfa: 53 push %rbx
400dfb: 48 83 ec 28 sub $0x28,%rsp
400dff: 89 fd mov %edi,%ebp
400e01: 48 89 f3 mov %rsi,%rbx
...
400e18: be ee 0d 40 00 mov $0x400dee,%esi
400e1d: bf 0e 00 00 00 mov $0xe,%edi
400e22: e8 89 fd ff ff callq 400bb0 <signal@plt>
400e27: ba 93 0f 40 00 mov $0x400f93,%edx
400e2c: 48 89 de mov %rbx,%rsi
0x400e22でsignal()を呼んでいるみたいなので、これを例に見てみます。
まずは0x400deeとかいうアドレスをesiレジスタに入れています。これはalarmhandleという関数のようです。
$ nm /bin/sleep | grep 400dee
0000000000400dee t alarmhandle
次に0xe(14)をediに入れています。
$ ruby -e 'printf("%d\n",0x0e)'
14
呼んでいるのはsignal()なので、シグナル番号なのでしょう。シグナル14番を調べると、SIGALRMのようです。
$ find /usr/include -type f \
> | grep signal \
> | xargs grep SIG \
> | grep 14 \
> | grep define
/usr/include/sys/signal.h:#define SIGALRM 14 /* alarm clock */
ということは、0x400e18から0x400e22にかけてはsignal()の呼び出し処理で、おそらくSIGALRMをalarmhandle()という関数でハンドルさせる処理のように見えてきます。
/bin/sleepのソースコードで答え合わせすると、ばっちり予想通りで、少しだけバイナリを読むレベルが上がった気になれます。
/usr/src/bin/sleep.c:
68 main(int argc, char *argv[])
69 {
...
79 (void)signal(SIGALRM, alarmhandle);
こんな感じで、NetBSDはプログラミング環境だけでなく、バイナリを読むための練習環境としても活用できます。
まとめ
今日の記事ではNetBSDをプログラミング環境として利用する方法を紹介してみました。明日からはryoonさんによるAdvent Calendarとなります。ぜひお楽しみに。