FreeBSDセットアップ「つまみぐい」その9 ちょっと手ごわいソフトウェアを使う # どれも有名なソフトウェアばかりで、ぐぐればいくらでも解説が見つかるし、 # 解説書も豊富なので、詳しくはそちらを参照。ここでは紹介だけに留める。 awkやらperlやらrubyやら http://aoki2.si.gunma-u.ac.jp/Hanasi/Algo/awk.html http://www.att.or.jp/perl/man/ http://www.ruby-lang.org/ja/ http://ruby.mirror.easynet.be/ja/uguide/uguide00.html http://www.python.jp/Zope/ どれも有名なインタープリタ言語で、非力だがsortやgrepなどの基本コマンドと 操作感が似ているawk、多少クセはあるが強力で汎用性も普及率も移植性も高いperl、 普及率はawkやperlに及ばないものの後発のためポテンシャルが高く今風なruby、 とそれぞれに特徴がある。 # この他にも、pythonやphpなど、いろいろなインタープリタ言語がある。 シェルから(主にテキスト処理をさせるために)使うことも可能で、たとえば、 > cat /dir1/CHECKSUM.md5 /dir2/CHECKSUM.md5 | awk '{print $4}' | uniq -d とやってMD5sumの一致するファイルを探したり、 > perl -pe 's/うんたら/かんたら/g' < file1 とやって正規表現を使った置換をしたりと、いろいろと便利な使い方ができる。 http://x68000.q-e-d.net/~68user/unix/pickup?awk http://x68000.q-e-d.net/~68user/unix/pickup?perl http://www.legacyst.com/naotokun/unixer/ # rubyもperlと同様、-pオプション(出力付き自動ループ)と # -eオプション(コマンドラインからスクリプトを指定)を指定して # シェルから利用できる。 シェル(もしくはシェルスクリプト)から呼び出して使う分にはawk(パイプを 使ってsedやgrepやuniqなどと併用する)が手軽だが、perlの方がスマートだし 複雑な作業にも対応しやすい。perlについては、Shell.pmとかperlshというのを 使って、コマンドインタープリタ的に使うことも可能らしい。 http://www.kt.rim.or.jp/~kbk/perl5.005/perlfaq3.html#Is_there_a_Perl_shell_ # 筆者はShell.pmの中身もperlshの中身も読んだことがないし、ほとんど理解していない。 正規表現も強力で、変態^h^h達人の域まで達している人たちもいる。 http://www.din.or.jp/~ohzaki/regex.htm # 後発のrubyも、(perlをお手本にしたらしく)強力な正規表現が可能なはずだが、 # 歴史が浅いためか、ここまで激しい話しは聞いたことがない。 正規表現自体については下記を参照。 http://www.kt.rim.or.jp/~kbk/regex/regex.html http://www.sixnine.net/regexp/ http://www5a.biglobe.ne.jp/~n_rieko/perl/8.htm http://www.ruby-lang.org/ja/20020314.html edコマンドを基準にした限定正規表現(Basic Regular Expression)と egrepコマンドを基準にした拡張正規表現(Extended Reuglar Exression)のほか、 perl互換の正規表現などいろいろなものあるが、基本的な部分はあまり変わらない。 そこそこの長さのスクリプトを書こうと思うとrubyが文句なしに強力だが、 手っ取り早さとパクリネタの多さではperlに一日の長がある。正規表現が強力で テキスト処理に強かったことから、フリーで公開されている学術用のデータ処理 スクリプトには、perlで書かれたものが多い。一方awkはどうしても非力だし 複雑な処理をさせようと思うとかなり手間がかかる(世の中には職人的な技術を 持った人もいるが、awkを相当愛していないとその域までは到達できないだろう)。 perlについては http://takenaka-akio.cool.ne.jp/doc/perl_kiso/ http://wisdom.sakura.ne.jp/programming/perl/ http://lll.physics.gifu-u.ac.jp/~tasaka/perl/ あたりが非常に参考になる。 perlスクリプトをWindowsマシンで動かすのは多少面倒だが、スクリプトから 実行形式のバイナリ(.exeファイル)を生成するツールもある。 # 最低1台は、perl(ActivePerl)が動くWindowsを用意する必要があるが。 PAR:スクリプトとインタープリタと利用するライブラリ(自動検出可能で 手動でも追加できる)を1ファイルにまとめる。作成したバイナリを公開する場合は、 インタープリタやライブラリのライセンスに注意する。 http://namazu.org/~satoru/diary/20040716.html http://perldoc.jp/docs/modules/PAR-0.75/script/pp.pod http://par.perl.org/ gldファイルを読み込む箇所を my $fileWindow=PAR::read_file('hoge.gld'); としておく(事前にuse PARはしておく)ことと、 デザインオブジェクトの生成方法を「newLoad」から「newScalar」に変更する my $objDesign = Win32::GUI::Loft::Design->newScalar($fileWindow) ことがポイントらしい。 http://take4.dynsite.net/mt/archives/000019.html perlcc:perlスクリプトをCのソースコードに変換してから普通にコンパイルする。 多分、生成されたCのソースを手動で修正するのが前提なのだと思う。perlを入れると 標準でバンドルされている(のだと思う、多分)。元のスクリプトが複雑だと 変換の精度も落ちるらしい(まあ当然)。 http://fleur.hio.jp/~hio/perldoc/mix/bin/perlcc.html perl2exe:PARと似たような方式(だと思う)。シェアウェア。 http://www.indigostar.com/perl2exe.htm rubyやphpにも似たようなツールがあるのだろうが、筆者は知らない。 viとかemacsとか viは「どんな環境でも動く」ことを前提に最大限の拡張を施したエディタで、 nviやBSD系で育ったvimなどの派生がある。 # debianがnviを「新 vi。オリジナルの vi と同じバグを持つ。」と # 紹介しているのにはちょっと笑った。 どんな環境でも動くというのは、シングルユーザーモードでの起動時に 利用可能であるということだけでなく、キーマッピンッグによっては 期待通りの動きをしない恐れのある特殊キー(BackSpace、Delete、Home、End、 PageUp、PageDownなどを含む)をまったく使わない操作が可能になっている。 # sshでリモート接続したときなどは特に、この操作体系がありがたい。 バッファ(クリップボードのようなもの)が使えたり、複数のファイルを 開けたりと、eeに比べれば格段に高機能なので、常用するかどうかは別として、 とりあえず一通りの操作を覚えておいて損はない(下記参照)。 http://www-lab.imr.edu/~ccms/Jpn/service/mint/vi/vi.htm http://www.net-newbie.com/linux/commands/vi.html emacsは「とにかくなんでもできる」エディタで、lisp派生のemacs lisp という 言語環境まで自前で持っている。xemacs、emacs21、muleなどの派生がある。 # 各派生ソフトウェアの関係については、筆者はよくわからない、 # というかemacs自体使ったことがない。 loader(8)のコマンド # 起動直後の「boot -s」などを入力できる画面のこと。ごく一部だけ。 http://www.jp.freebsd.org/cgi/mroff.cgi?subdir=man&lc=1&cmd=&man=loader&dir=jpman-5.2.0%2Fman§=0 http://www.jp.freebsd.org/cgi/mroff.cgi?sect=8&cmd=&lc=1&subdir=man&dir=jpman-5.2.0%2Fman&subdir=man&man=loader.4th boot カーネル名 カーネルを指定してブートする。 help トピック /boot/loader.helpの内容を表示。目次から見たい場合は> help index もしくは > ? とする。 lsとmore シェルコマンドと同様。 lsdevとlsmod モジュールがロード可能なデバイス/ロード済みのモジュールを表示。 loadとunload モージュールのロードと全クリア。 include ファイル名 スクリプトファイルの実行。 setとunset 環境変数の指定と削除。 pnpscan プラグアンドプレイデバイスのスキャン。FreeBSD5.2時点では未実装。 地味に便利なコマンドたち(手ごわくないものも含む) http://x68000.q-e-d.net/~68user/unix/genre.html システム情報 top システム内の上位プロセスをリアルタイムで表示。何が重いのかわからないが とにかくシステムが重いときに使ってみる。 vmstat 本来は仮想メモリの情報を表示するコマンドなのだろうが、CPUやディスクに 関する情報もわかる。情報は5秒ごとにサンプリングされているらしいので、 リアルタイムにモニタしたければ> vmstat -w 5 などとする。 lsvfs 現在ロードされている仮想ファイルシステムを表示。Linuxだと、シェルから lsdevやlsmodが使えるものやlspciでPCIデバイスの一覧を表示できるものも あるらしい。 df ディスクの情報(容量など)を表示。 swapinfo swap領域の情報を表示。書式はdfと同じ。 du ディレクトリ名 サブディレクトリの一覧を使用容量つきで表示。 ユーザー情報 id ユーザー名 ユーザーのuid、gid、所属するグループなどを表示する。ユーザー名を省略すると 自分の情報が出る。 who ログインしているユーザーの一覧を表示する。 whoami ユーザーIDを表示する。>idの方が情報が詳しい。 whois -h ドメイン管理元 メイン名 whoisデータベースを検索してドメインの所有者を調べる。 nslookup アドレス ネームサーバに問い合わせてFQDNとIPアドレスの相互変換を行う。 ファイル/コマンド情報 man コマンド名 マニュアルを表示する。 file ファイル名 ファイルの種類を表示する。 what ファイルを構成するオブジェクトモジュールのバージョンを表示する、らしい。 whatis > man -f と同じ、らしい。 where コマンド コマンドのフルパスを、重複したものも含めて優先順に表示する。csh系のコマンド。 whereis コマンド コマンドのフルパスやman、src、portsなどのパスを表示する。 which コマンドのフルパスを表示する。重複したものもはもっとも優先順位の高いもの だけが表示される。 ldd コマンド 動的リンクによって依存しているファイルを表示する。 ファイル検索 find ディレクトリ名 検索対象 処理 指定ディレクトリ以下から検索対象を見つけて処理を実行する、と書くと意味が わからないが、たとえば> find /usr/local -name myfile -ls とすると、 /usr/local以下から名前がmyfileのファイルもしくはディレクトリを探してパスなどを 表示する。単に> find myfile とした場合は、カレントディレクトリ以下からパス (この場合は相対パスで指定しているので相対パス)にmyfileを含むファイルを 探して-printする。 # プライマリ(-nameとか-userとか)をひとつも指定しなかった場合、たとえば # > find /usr/local myfile とした場合、なぜか絶対パスに/usr/localを含む # ファイルと相対パスにmyfileを含むファイルを両方羅列する(/usr/local以下から # myfileを含むファイルを探す、という挙動にはならない:FreeBSD4.9での動作)。 locate キーワード インデックスファイル(/var/db/locate.database)を利用したファイル検索。 >locate キーワード で> find / -name '*キーワード*' -print とほぼ同じらしい。 インデックスファイルは/usr/libexec/locate.updatedbで更新できる(cronから etc/periodic/weekly/のスクリプト経由で実行されている)。 文字列処理(文字コード除く) tee 標準出力とパイプの両方に出力を流す。Teeという高機能版がある。 > command | tee ファイル1 ファイル2 などとして使う。 # 上記の例だと標準出力とファイル1とファイル2に出力される。 uniq ファイル 同じ行が連続する場合は1行にまとめて表示する。uniq -c ファイル で重複の 回数をカウントできる。 sort ファイル ソート(辞書順もしくは数値の大小順に並べ替え)をして表示する。 > sort -u ファイル で重複行を1行にまとめて表示できる。+数字オプションで ソートの対象とするフィールドを選択できる(>sort +2 ファイル 先頭から2つ 後ろのフィールドを対象にソート:数字が0から始まっていることに注意)が、 省略した場合は+0を指定したのと同じ扱いになる。 文字コード coco 文字コードの判別。> cat ファイル名 | coco -q として使う。muleのコマンド。 iconv 文字コードの変換を行うが、たいていの場合nkfを使った方が楽。 > iconv -f 変換元コード -t 変換先コード < 変換元ファイル > 変換先ファイル として使うらしい。 nkf 文字コードの変換をして標準出力に表示する。-jでJIS、-sでSJIS、-eでEUC-JPに変換。 ファイルに出力したい場合は> nkf -e 変換元 > 変換先 などとリダイレクトする。 qkc 文字コードの変換をしてファイルを書き換える。nkfと同じく-j、-s、-eの オプションが使えるが、改行コードについても、-mでDos改行(CR+LF)に、-uで Unix改行(LF)に、-maでMac改行(CR)に変換できる。-zオプションを使うと ファイルの末尾の^Z(EOF)も削除できるらしい。 その他 wget URL(ファイルでもディレクトリでもOK) HTTPとFTPに対応したダウンローダー。> wget -r -l 10 -N URL とすると、 10階層まで再帰的にリンクをたどって、新しいファイルだけを、URLから ダウンロードしてくれる。fetchよりも高性能。ファイルはカレントディレクトリに 保存される。 talk 1対1でしか使えないチャットソフトのようなもの。 ************************************************************ ********** いいかげんなことばかり書いてあるので ********** ********** 転んでも泣かない人専用!       ********** ************************************************************ apache(HTTP) http://www.apache.jp/ http://httpd.apache.org/docs/ http://httpd.apache.org/docs-2.0/ja/ # どうしても必要でなければ、もっと軽いソフトウェアを使った方がよいと思う 本体インストール http://hiiro-sou.hp.infoseek.co.jp/unix/server/apache.html ports/www/apache13もしくはports/www/apache2をインストール。 /usr/local/etc/apache/httpd.confを適当に編集。待ち受けポートの番号、 管理者のメールアドレス、ドキュメントルート、ホストネームあたりが最低限の設定。 # portsを使わなかった場合、設定ファイルの場所が違うことがあるらしい # ホストネームは、最後の/を省略してディレクトリにアクセスした場合に # リダイレクト先URLの一部になるようなので、書かなくても動くからといって # 設定を省略しない(外からアクセスする場合に使うドメイン名を書く)。 ディレクトリのオプションは、とりあえずすべてNoneにしておくのが無難だろう。 mod_include、mod_cgi、mod_proxyなど、不要なモジュールは読み込みを止めておく。 # LoadModuleとAddModuleの部分をコメントアウトする。 設定ファイルの詳細 http://warp.syns.net/2/3/ http://www.unix-power.jp/linux/redhat/apache.html http://www.mikeneko.ne.jp/~lab/web/htaccess/ http://mononoke.dyndns.org/~kamada/freebsd/freebsdmain.htm # apache1.3の場合。2.x系でもそれほど大きくは変わらないと思う。 ディレクトリやファイルの設定書式は<カテゴリ>との間に命令を 書くようになっており、たとえば Options MultiViews AllowOverride None とあれば、ドキュメントルートからの相対パスが/cgi-binであるディレクトリで、 MultiViewsオプションを有効にして、.htaccessファイルでの上書きは禁止する、 という意味になる。 # たとえばドキュメントルートが/usr/local/www/dataである場合、 # は/usr/local/www/data/cgi-binを指す。 # ダブルクォーテーションでくくると絶対パスでの指定になるらしいので、 # としても同じ意味(のはず)。 のようにワイルドカードの利用も可能 DirectoryではなくDirectoryMatchで指定すると、拡張正規表現と呼ばれる 本格的な正規表現が使える。 # のようにチルダを挟んでも、 # DirectoryMatchを使った場合と同様に拡張正規表現が使えるが、 # これは歴史的な経緯らしく、どちらでも問題ないようだ # 一般に拡張正規表現を使う場合はダブルクォーテーションでくくる模様。 ファイル指定の場合などとFilesで指定する。 # 上記は拡張子が.cgiであるファイルすべてという意味 # これもチルダを挟むかFilesMatchで指定すると拡張正規表現が使える また、Optionsは有効にするものを+、無効にするものを-で表し、たとえば Options +Indexes -FollowSymLinks +Includes などと書くのが本来の書き方のようだ。 # +や-を省略した場合先頭に書いたもののみが有効になる。 # とりあえずすべて明示的に書いておくのが無難だろう。 この他にAllowとDenyでアクセス制御が設定でき、 Allow ホスト名 とかDeny ホスト名 などとする。 # 指定方法は、ホスト名(.で始めると前方一致)、IPアドレス(.で終わると後方一致)、 # サブネットマスクつきIPアドレス、allなど。 さらにOrderを指定してAllowとDenyの優先順序を決める。 # deny,allowはデフォルト許可>deny指定されたものを拒否>拒否された # もののうちallow指定されたものを改めて許可、allow,denyだとデフォルト拒否> # allow指定されたものを許可>許可されたもののうちdeny指定されたものを # 改めて拒否、mutual-failureだとallow指定されていてかつdeny指定されていない # ものを許可、ということになるが、allow,denyとmutual-failureは結局 # 同じ意味になる(書き方としてはallow,denyが推奨らしい) モジュールのインストール # portsのwwwセクションに入っているモジュールもあるが、 # ソースからのインストールも非常に楽なのでどちらでもよい。 # 以下はソースからのインストールについて。 欲しいモジュールのソースコードを入手して解凍する # モジュール名+ダウンロードあたりでぐぐればすぐ見つかるはず。 # たとえばmod_perlならhttp://perl.apache.org/からDownloadを選べばよい 展開時にできたディレクトリにC言語のソースコードがあるはず。 ソースコードを展開したディレクトリで > apxs -c C言語ソース でモジュールのコンパイル # 例 > apxs -c mod_perl.c # これでカレントディレクトリにmod_perl.soとmod_perl.oができる > apxs -i -a モジュールファイル(.so) でモジュールを有効にしてくれる # 例 > apxs -i -a mod_perl.so # これで/usr/local/libexec/apache以下にmod_perl.soがコピーされ、 # httpd.confも自動で更新される(バックアップも取ってくれるが、 # 一応手動でもバックアップしておいた方がよいだろう) あとは > apachectl graceful でやさしく再起動してやれば動くはず。 管理 メールのエイリアスを変更(その8のpostfixの項目を参照)し、webmaster宛てと www宛てのメールがrootに届くようにしておく。 # FreeBSDデフォルトの設定ファイルを使っているなら、 # SUPPORT MAILBOX NAMES FOR SPECIFIC INTERNET SERVER という項目の # コメントを外すだけでよい ログローテーションの際、1番ではなく30番のシグナルで再起動する ことになっているので注意が必要。 # apachectlの引数でいうと、restartではなくgracefulを使うということ。 その他 semdmailやwu-FTPDも、機会があれば(話のネタに)触ってみたいがちょっと怖い。 シェルスクリプトの作成(オマケ) http://naoya.dyndns.org/doc/script_howto.txt http://www15.big.or.jp/~yamamori/sun/boot/shell.html http://x68000.q-e-d.net/~68user/unix/pickup?test http://x68000.q-e-d.net/~68user/unix/pickup?%A5%B7%A5%A7%A5%EB%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8 http://www.jp.freebsd.org/cgi/mroff.cgi?subdir=man&lc=1&cmd=&man=sh&dir=jpman-5.2.0%2Fman§=0 http://www.jp.freebsd.org/cgi/mroff.cgi?subdir=man&lc=1&cmd=&man=test&dir=jpman-5.2.0%2Fman§=0 http://warp.syns.net/10/index.html 文法 # 基本的にインタープリタとなるシェルのコマンドラインと同じ。 # シェルで使える正規表現も同様に使える。 1行目はインタープリタ行で、#! /bin/sh などと、シャープ、エクスクラメーション、 スペースに続けて、コマンドを実行するインタープリタを指定する。 shの代わりにtcshなどを使ってもよいが、shを使っておくのが無難。 # 以下ではshを使うものとして話しを進める。 変数はVARIABLE=valueの形で設定し、${VARIABLE}という形で呼び出す。 $0や$1は引数を表し、$0には実行中のスクリプトの絶対パスが入っている。たとえば > /tmp/myscript.sh arg1 arg2 とした場合、/tmp/myscript.shが$0、arg1が$1、arg2が$2の値になる。 $?は最後に実行したコマンドからの戻り値を表し、$#は引数の個数を表す。 ダブルクオーテーションで囲った部分はひとまとまりの入力として扱われるが、 変数は展開(代入)される。シングルクオーテーションで囲った部分も ひとまとまりの入力として扱われるが、変数が展開されない(文字通りに解釈される)。 プライム記号で囲った部分には、コマンドの実行結果(出力)が代入される。 # ASCIIではシングルクォートとアポストロフィが0x27の「'」で # 逆クォートが0x60の「`」という扱いだが、もともとは「`'」でワンセットの # シングルクォーテーションだったとか、もっと前は # 「`」がグレイヴアクセント(アクサングラーヴ)で「'」がアポストロフィだったのを # シングルクォーテーションに代用しただけだとか、諸説あってよくわかんない。 たとえば、(#!で始まる行はコメントではなくインタープリタ行) #! /bin/sh VARIABLE=value echo "${VARIABLE}" echo '${VARIABLE}' echo "`basename $0` $1" という内容で/tmp/myscript.shを作成し、chmodで実行権限を与えてから > /tmp/myscript.sh arg として実行した場合、画面には value ${VARIABLE} myscript.sh arg と表示されるはず。 # basenameは、文字列から最後のスラッシュより後ろの部分を抜き出すコマンド。 ちなみに、 echo aada ; kouda と書いてしまうと(シェルで> echo aada ; kouda としたのと同じことになり)、 echoコマンドがaadaという文字列を表示した後koudaコマンドを実行しようとする。 echo "aada;kouda" としておけば、画面にaada;koudaという文字列が表示される。 # 常にダブルクォーテーションを使うクセをつけておくとよい。 分岐 case文による分岐は case "変数" in パターン1) ;; パターン2) ;; 以下分岐が終わるまで繰り返し esac という流れになる。最初のcase "変数" in の部分は、もし変数が以下の値なら、 という意味。パターンの部分では、変数の値がパターンに一致すれば次の行に進み、 一致しなければ次の値分岐まで読み飛ばす。;;の行を読むとesacの行まで読み飛ばす。 # ;;の行はパターンによる分岐が終わるたびに必ず必要。 たとえば、(便宜上行番号を振ったが、実際のスクリプトではこのように書かない) 1 case "$1" in 2 arg1) 3 echo "arg=1" 4 ;; 5 arg2) 6 echo "arg=2" 7 ;; 9 arg3) 10 echo "arg=3" 11 ;; 12 esac という内容で/tmp/myscript.shを作成し、chmodで実行権限を与えてから > /tmp/myscript.sh arg2 とすると、2行目を読んだ時点で$1の値がarg1ではないので5行目に進み、 5行目を読んだ時点で$1の値がarg2なので6行目に進み、6行目のコマンドを実行し、 7行目を読んで指示どおり12行目に進む。 # 想定していない値が入っていた場合にエラートラップするなら、 # *) # echo "error" # ;; # などといった分岐を最後に付け加えておく。 if文による分岐は if コマンド then then文による分岐の処理 else else文による分岐の処理 fi という流れになり、ifの後に続けて書いたコマンドを実行して、戻り値が 0ならthen以下、0以外ならelse以下を実行した後、fiまで読み飛ばす。 else文はなくてもよい。 # testコマンドと組み合わせて使うことがほとんど(下記参照)。 # http://www.jp.freebsd.org/cgi/mroff.cgi?subdir=man&lc=1&cmd=&man=test&dir=jpman-5.2.0%2Fman§=0 終了と戻り値 最後の行まで実行すると最後に実行したプロセス(上記の例だと、echoコマンド)が 返した戻り値をそのまま保持して($?を書き換えることなく)終了するが、 exit 戻り値 と書いておけば、その行を読んだ時点で指定した戻り値を返して終了する。 # exitとだけ書く(戻り値を省略する)と、$?を書き換えることなく終了する。 終了後にシェルから > echo $? とすれば、戻り値を確認できる。たとえば戻り値5でエラー終了した場合、 スクリプトをエディタで開いてexit 5 を検索すれば、どこでエラーが起きたのか 把握できる(エラー終了時にきちんとした戻り値を返すようになっていなければ 意味がないし、エラーメッセージを吐くようにした方が恐らく手っ取り早いが)。 起動のみ # 凝ったことをしないのなら、たいていの場合これだけで事足りる 以下の2行だけでよい。 #! /bin/sh 実行するコマンドを絶対パスで書く # 出力を捨てる場合は、コマンド > /dev/null 2>&1 としておく。 たとえば/usr/libexec/ftpdを-Dオプションつきで実行するなら、 #! /bin/sh /usr/libexec/ftpd -D とする。 コマンドが存在しないときのエラートラップ testコマンドを利用して、 #! /bin/sh if test -x コマンドの絶対パス then コマンドの絶対パス else 異常終了処理 fi などとする。 # ファイルの存在を調べるなら-f、実行可能かどうかまで調べるなら-xオプション # を使う。また、[ -x コマンドの絶対パス ]; then と書いても同じ意味になる。 異常終了処理は、 echo "error" >&2 などとエラーメッセージを吐いておく。 スタート、ストップ、再起動で分ける case分岐を使って #! /bin/sh case "$1" in start) 開始処理 ;; stop) 終了処理 ;; restart) 再起動処理 ;; *) 定義していない引数の処理 ;; esac などとする。 終了処理は、たとえば、 /bin/kill `cat pidファイルの絶対パス` # pidファイルは、デーモンが自分のPIDを書き込む拡張子.pidのファイルのことで # 普通は/var/run/以下だが、たとえばapacheならhttpd.confのPidFileという行で # 変更できる などとする(pidファイルがない場合はpsコマンドを使う)。 再起動処理は、たとえば、 /bin/kill -1 `cat pidファイルの絶対パス` もしくは /bin/kill -s HUP `cat pidファイルの絶対パス` として1番(HUP)のシグナルを送ってやればよい。 # 上の2つのコマンドはどちらも同じ意味。 定義していない引数の処理は、たとえば echo "Usage: `basename $0` {start|stop}" >&2 もしくは echo "invalid argument" >&2 などとしてエラーメッセージを吐いたうえで exit 64 などとして終了する。 # exit時の戻り値は、(portsで入れたときの起動スクリプトに64と # しているものが多いので)とりあえず64としているが、本来は # 違う値を返すのかもしれないし、2以上ならいくつでもよいのかもしれない。 # もしかすると1でもいいのかも(ようするに筆者はわかっていない)。 結局のところ #! /bin/sh case "$1" in start) if [ -x コマンドの絶対パス ]; then コマンドの絶対パス else echo "Command not found or permission error" >&2 fi ;; stop) if [ -r pidファイルの絶対パス ]; then /bin/kill `cat pidファイルの絶対パス` else echo "PIDfile not found or permission error" >&2 fi ;; restart) if [ -r pidファイルの絶対パス ]; then /bin/kill -s HUP `cat pidファイルの絶対パス` else echo "PIDfile not found or permission error" >&2 fi if [ -x コマンドの絶対パス ]; then コマンドの絶対パス else echo "Command not found or permission error" >&2 fi ;; *) echo "Usage: `basename $0` {start|stop|restart}" >&2 ;; esac などとすればよいことになる(はず)。 # エラーメッセージを吐いていることだし、エラー時の戻り値は設定しなかった。 さらにエラートラップをしつこくやるなら、コマンド実行の部分を if コマンドの絶対パス then 終了処理 else エラー処理 fi としておけばよい・・・と思ったのだが、よくない書き方らしいので、 コマンドの絶対パス STATUS="$?" if [ ${STATUS} eq 0 ]; then 終了処理 else エラー処理 fi とでもすればよいだろう。 特殊な変数のまとめ $数字 引数を番号で示す $# 引数の個数 $@と$* $0以外の全ての引数 $? 最後に実行したコマンドの返した戻り値 $! 最後に実行したバックグラウンドコマンドのPID $$ スクリプトを実行しているシェルのPID $- 現在のオプションフラグ $@と$*では展開のされ方が違い、$1=hoge、$2=moge、$3=pogeとなっている場合、 "$*"は"hoge moge poge"、"$@"は"hoge" "moge" "poge"と解釈される (クォーテーションで囲わなかった場合はどちらもhoge moge poge で同じ)。 利用可能なシェル組み込みコマンドの一覧 http://www.jp.freebsd.org/cgi/mroff.cgi?subdir=man&lc=1&cmd=&man=while&dir=jpman-5.2.0%2Fman§=0 http://www.jp.freebsd.org/cgi/mroff.cgi?sect=1&cmd=&lc=1&subdir=man&dir=jpman-5.2.0%2Fman&subdir=man&man=csh http://www.jp.freebsd.org/cgi/mroff.cgi?sect=1&cmd=&lc=1&subdir=man&dir=jpman-5.2.0%2Fman&subdir=man&man=sh コマンド 外部 csh(1) sh(1) alias Yes Yes Yes alloc No Yes No bg Yes Yes Yes bind No No Yes bindkey No Yes No break No Yes Yes breaksw No Yes No builtins No Yes No case No Yes Yes cd Yes Yes Yes chdir No Yes Yes command Yes No Yes complete No Yes No continue No Yes Yes default No Yes No dirs No Yes No do No No Yes done No No Yes echo Yes Yes Yes echotc No Yes No elif No No Yes else No Yes Yes end No Yes No endif No Yes No endsw No Yes No esac No No Yes eval No Yes Yes exec No Yes Yes exit No Yes Yes export No No Yes false Yes No Yes fc Yes No Yes fg Yes Yes Yes filetest No Yes No fi No No Yes for No No Yes foreach No Yes No getopts Yes No Yes glob No Yes No goto No Yes No hash No No Yes hashstat No Yes No history No Yes No hup No Yes No if No Yes Yes jobid No No Yes jobs Yes Yes Yes kill Yes Yes No limit No Yes No log No Yes No login Yes Yes No logout No Yes No ls-F No Yes No nice Yes Yes No nohup Yes Yes No notify No Yes No onintr No Yes No popd No Yes No printenv Yes Yes No pushd No Yes No pwd Yes No Yes read Yes No Yes readonly No No Yes rehash No Yes No repeat No Yes No sched No Yes No set No Yes Yes setenv No Yes No settc No Yes No setty No Yes No setvar No No Yes shift No Yes Yes source No Yes No stop No Yes No suspend No Yes No switch No Yes No telltc No Yes No test Yes No Yes then No No Yes time Yes Yes No trap No No Yes true Yes No Yes type No No Yes ulimit No No Yes umask Yes Yes Yes unalias Yes Yes Yes uncompleteNo Yes No unhash No Yes No unlimit No Yes No unset No Yes Yes unsetenv No Yes No until No No Yes wait Yes Yes Yes where No Yes No which Yes Yes No while No Yes Yes