日記

日記というか筆者の設定メモです。内容が古くなった上に 間違いがたくさんあります。

Mon May 22

今日須崎ケーブルテレビ と契約をした。CATVインターネットのモニターを募集していたからです。これの良いところは 電話代を気にせずwebサーフィンできて、ダイアルアップよりもはるかに早いということ です。


Tue May 23

LANボードがもう一枚いるということで(もう一枚は家庭内LAN用つまり2枚挿しになる) 買うことにしました。パーツを買う時、筆者はインターネットショップを良く利用する。 今回は送料が無料で品数の多いPC-PARK にアクセスしてみたするとプラネックッスコミュニケーションズ(株)のENW-8300-T (PCIバス 10Base-T)が1,110円だったのでこれに決めた。


Wed May 24

LANボードには100Base-Tと10Bese-Tの2種類のものが有る。CATVの場合には10Base-T のボードが使われる。IPアドレスはDHCPサーバより取得となっている。Windowsの設定は 解るのだがFreeBSDの設定はややこしい。 FreeBSD QandA 392 によるとDHCPサーバ、クライアントにはwide版とisc版があるようです。isc版は FreeBSD 3.2-RELESE以降のものには標準で付いているとのことで、我が家には FreeBSDをインストールしたパソコンが2だい有って、一方が3.1でもう一つは3.4なので この3.4の方をDHCPクライアントにすることにした。設定ファイルは/etc/dhclientですが このなかで /etc/dhclient-scriptを使っているこの中身をみてみると/etc/resolv.conf を書き換えるようである。我が家ではDNSサーバを立ち上げているのでちょっと都合が悪い。
<補足>resolv.confをresolv.conf.dhclient のように書き換えるようにスクリプトの内容を変更しています。
dhclientの起動方法は/etc/rc.confにifconfig_ed0="DHCP"(ed0はインタフェース名) を追加するか
rootでコマンドラインからdhclient ed0 とタイプしてもよいです


Sat 27 May

LANボードのENW-8300-TをTYAN Trinity 400 に付けることにした。FreeBSDでの認識は 以下のようなものです。

ed1: <NE2000 PCI Ethernet (RealTek 8029)> rev 0x00 int a irq 3 on pci0.17.0
ed1: address 00:90:cc:a4:37:c5, type NE2000 (16 bit)
rl0: <RealTek 8139 10/100BaseTX> rev 0x10 int a irq 11 on pci0.20.0
rl0: Ethernet address: 00:00:e8:9f:4f:49
rl0: autoneg complete, link status good (half-duplex, 10Mbps)

新しく付けたENW-8300-Tはed1として認識された。rl0は内部ネットワーク用に前から 付けていたものです。実はこのLANボード、どこにもベンダー名が記されていない。 ミックで1280円で買ったものだ。


Sun 28 May

FreeBSDでNAT(Network Adress Translator)をするためにはnatdを使う方法とip-filter を使う方法が有る。今回はnatdを使う方法がTRY!PC4月号に掲載されていたのでnatdを 使ってみることにした。 (NATに関しては RFC1631を参照してください。)

# cd /sys/i386/conf
# cp GENERIC MYKERNEL
# vi MYKERNEL
編集内容
不必要な行を#でコメントアウトする。(不可欠なものまで#を付けないように注意)

pseud-device bpfilter 1 #Berkeley packet filter
の数字を1から4に変更する。

以下の2行を追加する。
options IPFIREWALL
options IPDIVERT
以上が編集内容です。

# config MYKERNEL
# cd ../../compile
# make depend
# make
# make install
以上でカーネルの再構築は終りです。

次にデバイスファイルを作ります。
# cd /dev
# sh MAKEDEV bpf3

/etc/rc.confに以下の行を追加します。
natd_enable="YES"
natd_interface="ed1" #ケーブルモデムにつなげるLANボードのインタフェイス、ここではed1
natd_flags="-s -m -dynamic"
firewall_enable="YES"
firewall_type="open"

リブートします。
# shutdown -r now
以上で設定は終りです。

Tue 30 May

今日はCATVの工事です。工事は2時間ぐらいかかりました。DHCPクライアントの設定は /stand/sysinstallでやってみることにしました。Interfaceの設定でed1を選択後 "DHCPの設定を試してみますか?"に"はい"を選択すると自動でゲートウェイアドレス DNSサーバアドレスIPアドレスなどが設定される。気になる設定ファイルであるが /etc/rc.confには ifconfig_ed1="DHCP"が追加されている。/etc/resolv.confは新しいネームサーバの アドレスになっていた。気になる/etc/dhclient.confであるが中身はコメント行 があるだけでした。リブートして以下の行を試してみました。

% ifconfig -a
ed1: flags=8843 mtu 1500
        inet 192.168.XXX.XXX netmask 0xffffff00 broadcast 192.168.XXX.255
        ether 00:90:cc:a4:37:c5 
    <以下略>

inet 192.168.XXX.XXXがDHCPサーバより割り当てられたIPアドレスです。 このIPアドレス毎回違うものが割り当てられると思っていたのだがいつも同じ のようです。/var/db/dhclient.leasesにこのIPアドレスのリース期間が記述 されている。renewの項目が2017になっていることから西暦2017年までこのIPアドレス らしい。別のパソコンからもwebにアクセスできた。別にこのようにめんどうなことを しなくてもケーブルモデムからの10Base-Tのケーブルをハブにつないで各パソコンを DHCPクライアントにすればよいのだがnatdを試してみたかったことがあった。現に このようなつなぎ方を認めていないCATVもあります。つまりケーブルモデムにつなぐ パソコンは1台だけで複数台つなぐ場合はそのパソコンにproxyサーバソフトを インストールしてくださいというようなものです。

現在ケーブルモデムは3Comのサメのヒレの形をしたものに 変更になりました。このモデムは一つのLANボードしか認識しないのでHUBにつないで 複数のパソコンがケーブルテレビのDHCPサーバからIPアドレスを取得することはでき ません。


Wed Jun 14

yahooのオークション でエプソンのスキャナGT-8500を落札した。落札価格は9250円である。古い機種なので少し高かったかも しれない。ただ付けてくれたスカジケーブルのパソコン側のコネクタが合わず近所の 電機屋に買いに行ったが8000円もした。ケーブルがこれほど高いとは計算に入れてなかった。 FreeBSDでスキャナを使うにはsaneというソフトを使う。Windowsで使うTWAINのようなものだ。 GT-5500とGT-7000は動くようである。GT-8500は動くかどうかわからない。


Thu Jun 15

FreeBSDにソフトをインストールするにはpackageかportsをつかう。packageを使った方が 簡単で確実にインストールできるのだが今回はportsを使ってみることにした。しかも スカジボードの付いているマシンはFreeBSD3.1でportsツリーも古くなっているのでこれを cvsupで新しいものに変えることにした。まずcvsupのインストールportを試みたがエラーで ストップ、しかたなくpackageでインストール、つぎに3.1から3-stableへのアップグレード キットをpkg_addする。そして/usr/share/examples/cvsup/ports-supfileを~/my_ports-supfile などとコピーし編集する。変更箇所は*default host=CHANGE_THIS.Free.BSD.orgの所を *default host=cvsup2.jp.FreeBSD.orgのように変え、*default base=/usrを *default base=/usr/local/etc/cvsupとする。X上でcvsup my_ports-supfile とすると、ウィンドウが開きファイルのダウンロードが始まり/usr/ports以下のファイルを 更新してゆく、だいたい18k/sのスピードである。ダイアルアップの時は早くても6〜7K/s だったので、約3倍のスピードである。これが終るとcd /usr/ports/grahics/saneとし makeとタイプした。がgtk12のconfigureの所でエラーになりストップした。portsでインストール する時はよくあることである。


Thu Aug 17

GT-8500動作報告

スキャナのepson GT-8500がsane1.02で動作しました。 動作リストにはGT-8500はなかったけれど 問題なく画像をスキャンできました。スキャンした画像は これです。

インストールの方はなかなかうまくいかなかったのですが簡単に手順を言うとXfree86-3.3.3.1を XFree86-3.3.3.6にバージョンアップ、gtkのconfigureでエラーになることから古いバージョンのgtkを削除して みてはどうかということでgtk-1.0.,gtk-1.1.*をpkg_deleteするのですが、 依存関係があるのでenlightenment-0.15.*,gimp,imlib,を先に削除しますgtkを削除したらglibも削除します。 まずenlightenmentをインストール。cd /usr/ports/x11-wm/enlightenmentとしてmake バージョンは0.16.4です。しかしまたもやgtk12でストップ、しかたないのでgtk12はpackageで インストールしました。そうするとenlightenmentのmakeがとおりインストールすることができました。 enlightenmentを立ち上げて見ると見事に起動しました。やはりいいですねenlightenmentは。 バージョンアップをして良かったと思いました。 次にgimpをインストールです。バージョンは1.1.24です。順調にmakeしていきましたが、 libxpg4.so.3がないといってstopしてしまいました。そこで 検索のページで探してみると ln -s /usr/bin/libxpg4.so.2 /usr/bin/libxpg4.so.3とすれば良いという投稿があったので そのようにすればmakeすることができました。gimpのインストールの次がsane-1.02です。 これはmake ; make installですんなりできました。

   # camcontrol devlist
   <  >                               at scbus-1 target -1 lun -1 (xpt0)
   <EPSON SCANNER GT-8500 1.26>       at scbus0 target 5 lun 0 (pass0)
   <MATSHITA CD-R   CW-7502 4.10>     at scbus0 target 6 lun 0 (pass1,cd0)
   <  >                               at scbus0 target -1 lun -1 ()

スキャナは/dev/pass0で認識されています。そこで

# cat /usr/local/etc/sane.d/epson.conf
/dev/scanner
となっていますので、これを/dev/pass0のように書き換えます。
/dev/pass0を一般ユーザーからもアクセスできるようにします。
# chmod 666 /dev/pass0
一般ユーザに戻ってxscanimageをgimpから使えるようにリンクを張ります。
% mkdir ~/.gimp-1.1/plug-ins
% ln -s /usr/local/bin/xscanimage ~/.gimp-1.1/plug-ins
% scanimage --help
最後に利用可能なデバイスのリストが表示されます。
List of available devices:
epson:/dev/pass0
% setenv LANG ja_JP.EUC
% gimp.setfont japanese
% gimp &
拡張 -> Acquire Image -> Device dialogまたはepson:/dev/pass0とすると
xscanimageが起動されます。スクリーンショットはこれ(158K)です。

参考リンク

SANEのホームページhttp://www.mostang.com/sane/
日本語ドキュメント
SANE-outline-JP
SANE-tutorial-JP
ちなみにsane-1.00は問題ありです。sane-1.01は動きます。
40060
40067

Sat Aug 26

IP-FILTER

前にFreeBSDでNAT(Network Addrress Traslator)を実現する方法natdを紹介したがもう一つの 方法のIP-FILTERの設定について述べてみます。 LANボードは2枚挿しでケーブルモデムにつながっているボードはed1で認識され、DHCPクライアント は設定済とします。

# cd /sys/i386/conf
# cp GENERIC MYKERNEL
# vi MYKERNEL
ident GENERICをMYKERNELとする
以下の2行を追加する。
options IPFILTER
options IPFILTER_LOG
bpf(Berkley Packet Filter)を有効にし、フィルターの数を1から4に変更する。
pseudo-device bpfilter 4 #Berkeley packet filter
以上が編集内容です。
# config MYKERNEL
# cd ../../compile/MYKERNEL
# make depend
# make
# make install
bpfのデバイスファイルを作ります。
# cd /dev
# sh MAKEDEV bpf0 bpf1 bpf2 bpf3 設定ファイルを編集します。
# vi /etc/ipf.conf
pass in from any to any
pass out from any to any
# vi /etc/ipnat.conf
map ed1 192.168.1.0/24 -> 0/32 portmap tcp/udp 10000:65000
map ed1 192.168.1.0/24 -> 0/32
ed1はケーブルモデムにつながっているインタフェース名です。
ダイアルアップの場合はtun0のようになります。
192.168.1.0/24は内部ネットワークのIPアドレスです。
この例では192.168.1.1〜192.168.1.224のアドレスになります。
# vi /etc/rc.local
/sbin/ipf -f /etc/ipf.conf
/usr/sbin/ipnat -f /etc/ipnat.conf
# vi /etc/rc.conf
gateway_enable="YES"を追加します。
# shutdown -r now
以上です。

IP-FILTERについての詳しい情報は http://cheops.anu.edu.au/~avalon/ip-filter.htmlを参考にしてください。

FreeBSD 4.4での設定は少し違っていました。 これを参考にしてください。


Fri 7 Oct

Turbolinuxをインストールしました。

マザーボードはTyan S1854 Trinity 400,ハードディスクはseagate ST313021A,12419MB w/512kB Cache,CHS=1583/255/63です。このマシンには Windows98 2.4G FreeBSD 4.3G Windows2000 3.2G 残り2.6Gでパーテションされており この残り2.6Gにlinuxをインストールするのですが、一つ問題があってlinux標準のブートローダであるliloは1024シリンダまたは8Gを越える領域のOSは起動できないのです。 そこでliloはMBRにインストールせずにルートパーテションにインストールして MBRにブートセレクターのMBM などをインストールすれば良いかなと思ったのですが、この方法はだめでした。 順をおって説明して行きます。

CD-ROMが認識されない

BIOSでブートの順番をCD-ROMから起動できるように変更してインストーラを 起動します。ところがなぜかCD-ROMが認識されないのです。しかたないので NFS(Network File System)でインストールすることにした。別のFreeBSDマシンを NFSサーバにするのですが、NFSについては以前から知っていたのですが設定の 方法がわからなかった。 捜して見ると ハンドブック16.4. NFSにのっていた。 ハンドブックは 更新され続けているようである。ローカルマシンのハンドブックにはのっていない。

NFSサーバの設定
# vi /etc/rc.conf
nfs_server_enable="YES"
nfs_server_flags="-u -t -n 4"
mountd_flags="-r"
# vi /etc/exports
/cdrom -ro <マシン1> <マシン2> <マシン3>
-roはリードオンリー、マシン1、2、3は/etc/hostsに記述されているもの
再起動するか以下のコマンドを実行する
# nfsd -u -t -n 4
# mountd -r
これで別のFreeBSDマシンのCD-ROMを使えるようになりました。
詳しくはハンドブック16.4. NFSを参照のこと。

liloのインストールエラー

liloをルートパーティションにインストールするのですがエラーになって インストールできません。 サポートのFAQ によるとルートパーティションが拡張領域にあるとエラーになるそうです。 そこでliloを使うのはあきらめて liloを使わずにシステムを起動する方法がサポートのFAQにあったので これでやってみるとlinuxを起動することができました。

[root@kitora manabe]# /sbin/fdisk -l

ディスク /dev/hda: ヘッド 255, セクタ 63, シリンダ 1583
ユニット = シリンダ数 of 16065 * 512 バイト

 デバイス ブート   始点      終点  ブロック   ID  システム
/dev/hda1   *         1       309   2482011    b  Win95 FAT32
/dev/hda2           310       850   4345582+  a5  BSD/386
/dev/hda3           851      1250   3213000    7  HPFS/NTFS
/dev/hda4          1251      1583   2674822+   5  拡張領域
/dev/hda5          1251      1581   2658726   83  Linux
/dev/hda6          1582      1583     16033+  82  Linux スワップ

hda: ST313021A, 12419MB w/512kB Cache, CHS=1583/255/63

kterm上で実行した結果です。日本語で表示されるのがすごい。これでみるとLinuxの 領域は拡張領域になっています。基本領域は一つのHDDに4つまでとなっているので Linuxスワップの領域があるためLinuxの領域は必然的に拡張領域となるのではないか。

<注意>ここでは重大な計算間違いをしています。なんと スワップ領域が8.2MBしかありません。スワップ領域は実メモリの2倍、実メモリが 512MB以上の場合は同じかそれ以上とる必要があります。 しかしこれでも問題無く動作しました。

[root@kitora manabe]# /sbin/lilo
Warning: device 0x0305 exceeds 1024 cylinder limit
Fatal: geo_comp_addr: Cylinder number is too big (1462 > 1023)

これをみるとliloは基本領域でも1024シリンダ以降はインストールできないのでは ないだろうか。CD-ROMを認識させるためにはLILO:とプロンプトに続けて hdc=cdromとタイプしなければならないとやら。CD-ROMもあきらめるか。

liloを使わずにシステムを起動する方法では GNU GRUBを紹介しています。
grub> root (hd0,4)
 Filesystem type is ext2fs, partition type 0x83

grub> kernel /boot/vmlinuz-2.2.13-33 root=/dev/hda5
   [Linux-bzImage, setup=0xe00, size=0xa09e0]

grub> boot

--------

grub> root (hd0,1,a)
 Filesystem type is ffs, partition type 0x7a5

grub> kernel /kernel
   [FreeBSD-elf, <0x100000:0x148072:0x0>,<0x249074:0x1b360:0x21e30>,entry=0x1186f0]

grub> boot

---------

grub> root(hd0,0)
 Filesystem type is fat, partition type 0xb

grub> chainloader +1

grub> boot
キー配列が違うので注意。
例えば root (hd0, タブキーを叩くとリストが表示される。
マルチブートについてとても参考になるホームページがありました。
Nobusan's Square
ここの"ハードウェア関連"の"ブートとハードディスクのすべて"です。とても詳しくかかれています。例えばfdiskの基本領域、拡張領域、論理領域などの用語がよくわからなかったのですがここでは詳しく説明されています。

Mon 30 Oct

mount -o ro /dev/cdrom /mnt/cdrom

前回に引続きTurbolinuxの話題です。FreeBSDと基本的なコマンドは共通していますが違うところもあるので。インストールのときCD-ROMが認識しなかったのはなぜだろう CD-ROMが使えないのは面白くない。

$ dmesg | less
        .
        .
hda: ST313021A, ATA DISK drive
hdc: ATAPI CD ROM DRIVE 40X MAX, ATAPI CDROM drive
ide0 at 0x1f0-0x1f7,0x3f6 on irq 14
ide1 at 0x170-0x177,0x376 on irq 15
hda: ST313021A, 12419MB w/512kB Cache, CHS=1583/255/63
hdc: packet command error: status=0x51 { DriveReady SeekComplete Error }
hdc: packet command error: error=0x54
ATAPI device hdc:
  Error: Illegal request -- (Sense key=0x05)
  Parameter list length error -- (asc=0x1a, ascq=0x00)
  The failed "Mode Sense" packet command was: 
  "5a 00 2a 00 00 00 00 00 18 00 00 00 "
hdc: packet command error: status=0x51 { DriveReady SeekComplete Error }
hdc: packet command error: error=0x54
ATAPI device hdc:
  Error: Illegal request -- (Sense key=0x05)
  Parameter list length error -- (asc=0x1a, ascq=0x00)
  The failed "Mode Sense" packet command was: 
  "5a 00 2a 00 00 00 00 00 18 00 00 00 "
Uniform CDROM driver Revision: 2.56
     以下略

CD-ROMはセカンダリのマスタに接続している。hdc: packet command error と言うエラーが出ている。日本のLinux情報 で調べてみるとこれはCD-ROMがメディアを読みにいっているのではないかと判断して メディアを入れて再起動させてみたが同じでした。/etc/fstabには/mnt/cdromの 項目がありません。hdc: ATAPI CD云々とあることからなんか使えるようになっているのではないかという気がします。JFのIDE-CDドライバに関する文書や これで述べているローカルファイルfile:/usr/src/linux-2.2.13/Documentation/ide.txtが参考になります。

# ln -s /dev/hdc /dev/cdrom
# mount -t cd9660 -o ro /dev/cdrom /mnt/cdrom
#

エラーメッセージが返ってこなければマウントできた ことになります。何だ最初から使えるようになっていたのかという感じです。 /dev/cdromの代わりに/dev/hdcでもOKです。"-o ro"はリードオンリーのオプションです。"-t cd9660"でファイルシステムのタイプの指定ですが省略できます。

# cat /proc/filesystems
        ext2
nodev   proc
        iso9660
nodev   devpts
        vfat
        hpfs

ここにファイルシステムが登録されていれば自動でマウントするようです。 マウントをはずすのは/mnt/cdrom以外のディレクトリに移動してumount /mnt/cdrom です。CD-ROMが使えるのがわかったので/etc/fstabに/dev/cdromの項目を追加します。

# vi /etc/fstab
/dev/hda5               /                       ext2    defaults        1 1
/dev/hda1               /dos                    vfat    defaults        0 0
/dev/hda3               /nt                     hpfs    defaults        0 0
/dev/hda6               swap                    swap    defaults        0 0
/dev/fd0                /mnt/floppy             ext2    noauto,user     0 0
/dev/cdrom              /mnt/cdrom              iso9660 noauto,ro,user  0 0
proc                    /proc                   proc    defaults        0 0
none                    /dev/pts                devpts  mode=0622       0 0

/dev/hda3はntfsですがmountできません。またFreeBSDの領域もlinuxからはmount できません。


Sun Mar 11 2001

シェルプログラミングは楽し

例えばあるディレクトリに001.html,002.html・・・400.htmlのように400個の htmlファイルを作らなければならない、そしてそれぞれのファイルは一箇所だけ 違っている。

% cat 001.html
<html>
<head>
</head>
<body bgcolor="white" text="black">
<center>
<img src="img/001.jpg" border="0">
</center>
</body>
</html>

上記のimg src="img/001.jpg"の所001が002,003,004・・・400のように変化する。 これを一つ一つ書いていたのでは非常に時間がかかる。そこで001.htmlだけ書いて あとの002.htmlから400.htmlはシェルスクリプトでやってみることにする。

% cat > html.sh
#!/bin/sh
COUNT=1
while [ $COUNT -lt 400 ]
do
      COUNT=`expr $COUNT + 1`
      sed "s/001/`printf "%03s" $COUNT`/" 001.html > `printf "%08s" ${COUNT}.html`
done
Ctrlキーを押しながらDキーを叩く

html.shというファイルを作りchmod +x html.shとして実行権をあたえ./html.shとして 実行してみる。./はカレントディレクトリを表す、実行ファイルはカレントディレクトリ にあってもパスを表示しないと実行されません。(FreeBSDで)するとのこり399個 のファイルができます。これは何個でも同じで上記の400の所を好きな数字に変えればよい

   #!/bin/sh
       Bシェルの宣言をします。
   COUNT=1
       変数"COUNT"に1を代入します。"="の両辺にはスペースをいれません。
   while [ $COUNT -lt 400 ]
       変数"COUNT"が400より少ない場合はdoからdoneの間のことを繰り返す。
       変数を参照する時は$(ドルマーク)を付けます。-ltはLess Thanの略で
       より少ないという意味。以下本の写しですが
            -lt    未満       less than
            -le    以下       less equal
            -eq    同じ       equal
            -ge    以上       greater equal
            -gt    より上     greater than
            -ne    等しくない not equal   
    COUNT=`expr $COUNT + 1`
       変数"COUNT"に1を足して変数"COUNT"に代入します。
       `(逆シングル・クオテーション)で囲っていることに注意してください。
       exprというコマンドが含まれるために、ここは'(シングル・クオテーション)
       ではなく`(逆シングル・クオテーショオン)で囲みます。exprは式を評価
       するコマンドです。
    sed "s/001/`printf "%03s" $COUNT`/" 001.html > `printf "%08s" ${COUNT}.html`
        sedはストリームエディタと呼ばれるものです。001.htmlから001の文字列を
        `printf "%03s" $COUNT`で出力された文字列に変換し 
        `printf "%08s" ${COUNT}.html`で出力されたファイルに書き出します。
        printfは書式設定をするコマンドで "%03s"の 0 は空白部分を 0で埋め、
        3は3桁の意味、sは文字列です。$COUNTは 2,3,4…50…400が002,003,004
        …050…400のように変換されます。sedの書式は次のようなものです。

        sed 's/変換対象文字列/変換後の文字列/g' 変換前ファイル > 変換後ファイル

        gは一行内で繰り返し変換を行なうためのフラグ これがないと最初に
        でて来る文字列だけしか変換されません。また今回の例では '(シングル・
        クオテーション)ではなく "(ダブル・クオテーション)で囲っていることに
        注目してください。これがシングル・クオテーションだと
        `printf "%03s" $COUNT`の部分をそのまんまの文字列であるとシェルは
        解釈します。

参考文献

モガミワイヤーのUNIXの楽しみ

WindowsやMacはユーザーがお金を払うためのOSで それにたいしてUNIXはユーザが お金を生み出すOSと言っている。UNIXとは凄いんだなと思いました。

FreeBSD快適操縦ガイド 山口至著 メディア・テック出版

良く使うコマンドやシェルスクリプトの解説など初心者向けに書かれた本です。 とても参考になりました。

UNIXプログラミング環境Brian W.kernighan, Rob Pike,石田晴久 監訳、アスキー 出版局

古い本ではあるが、古典的名著らしい。初心者にはとっつきにくいかも知れないが モガミワイヤーさんの言うUNIXの思想を理解するのには良いかも。


Sun Mar 18

シェルプログラミングは面白い

今回はカレントディレクトリのJEPEG画像をすべてサムネイルで表示する HTMLを作ります。

% ls
ant.jpg         butterfly.jpg   cow.jpg         horse.jpg       raccoon.jpg
bird.jpg        cat.jpg         dog.jpg         mouse.jpg       sheep.jpg

このようなファイルがあるとします。これらの画像ファイルを元の大きさの 10%で全て表示するHTMLを作るプログラムです。これをthumbnail.shとします。

% cat thumbnail.sh
#!/bin/sh
 printf "<html>\n<head>\n</head>\n<body>\n" > THUMBNL.html
for i in `ls *.jpg`
do
        echo "<img src=\""$i"\" width=\"10%\" heigt=\"10%\">" >> THUMBNL.html
done
 printf "</body>\n</html>\n" >> THUMBNL.html

これにchmod +x thumbnail.shとし~/binにコピーしておくと良いでしょう。 source ~/.loginとして実行してみましょう。

(補足:ログインシェルがcshの場合です。~/.loginのset pat = のところに $HOME/binの記述がなくては行けません。shのばあいは~/.profileです。)
% thumbnail.sh
% ls
THUMBNL.html    butterfly.jpg   dog.jpg         raccoon.jpg
ant.jpg         cat.jpg         horse.jpg       sheep.jpg
bird.jpg        cow.jpg         mouse.jpg

THUMBNL.htmlというファイルができています。

% cat THUMBNL.html
<html>
<head>
</head>
<body>
<img src="ant.jpg" width="10%" heigt="10%">
<img src="bird.jpg" width="10%" heigt="10%">
<img src="butterfly.jpg" width="10%" heigt="10%">
<img src="cat.jpg" width="10%" heigt="10%">
<img src="cow.jpg" width="10%" heigt="10%">
<img src="dog.jpg" width="10%" heigt="10%">
<img src="horse.jpg" width="10%" heigt="10%">
<img src="mouse.jpg" width="10%" heigt="10%">
<img src="raccoon.jpg" width="10%" heigt="10%">
<img src="sheep.jpg" width="10%" heigt="10%">
</body>
</html>

画像が何百個あっても同じです。そのかわり読み込みに時間が かかりますが。このように簡単なコマンドの組合せで面白いことができるのが シェルプログラミングの魅力です。


Fri Apr 6 2001

パソコンの見積り

友人からパソコンの見積り依頼があった。

% cat mistumori.txt
CASE MaxPoint CS-658QX 300W電源 Pentium4対応  \8,980  faith
MB ECS K7VZA v3.0 KT133A(266mhzCPU対応)      \10,970  faith
CPU K7 Athlon ThunderBird 1.2GHz SocketA BOX  \28,770  faith
MEMORY PC-133 128MB SDRAM CL3                  \4,570  faith
OS WindowsMe OEM版                            \12,700  faith
HDD Fujitsu MPG3409AT-E 流体軸受けタイプ40G  \12,570  faith
FDD 松下 JU-257A/ 2モードFDD                  \1,570  faith
CDRW/DVD RICOH RW9120A OEM +B's Recorder Gold \27,700  faith
 +PowerDVD VR-X
VGA HIS GeForce256 AGP 32MB リテール          \6,970  faith
CRT 飯山電機 A705MKIT(WirelessKey,Mouse付)    \29,680  pc-park
送料                                           \2,200  faith
                                           -----------

バックラッシュのあとの数字は価格で空白のあとの文字列は店名です。 ここまで書いたら『あこれはシェルにやらせてみよう。』と思うのが 人情というものです。viを日本語対応にしたelvisというエディタを使って スクリプトを書いてみました。

% elvis mistumori.sh
#!/bin/sh
cat $1
cat $1 | awk -F \\ '{print $2}' | tr -d , | awk '{ s = s + $1 } 
 END { printf"%43s,%5d,%03d\n","小計",s / 1000,s % 1000 }  
 END { printf"%43s,%5d,%03d\n","消費税",s * 0.05 / 1000,s * 0.05 % 1000 }  
 END { printf"%43s,%5d,%03d\n","合計",s * 1.05 / 1000,s * 1.05 % 1000 }'
% chmod +x mistumori.sh
% ./mistumori.sh mistumori.txt
CASE MaxPoint CS-658QX 300W電源 Pentium4対応  \8,980  faith
MB ECS K7VZA v3.0 KT133A(266mhzCPU対応)      \10,970  faith
CPU K7 Athlon ThunderBird 1.2GHz SocketA BOX  \28,770  faith
MEMORY PC-133 128MB SDRAM CL3                  \4,570  faith
OS WindowsMe OEM版                            \12,700  faith
HDD Fujitsu MPG3409AT-E 流体軸受けタイプ40G  \12,570  faith
FDD 松下 JU-257A/ 2モードFDD                  \1,570  faith
CDRW/DVD RICOH RW9120A OEM +B's Recorder Gold \27,700  faith
 +PowerDVD VR-X
VGA HIS GeForce256 AGP 32MB リテール          \6,970  faith
CRT 飯山電機 A705MKIT(WirelessKey,Mouse付)    \29,680  pc-park
送料                                           \2,200  faith
                                           -----------
                                       小計,  146,680
                                     消費税,    7,334
                                       合計,  154,014

それではスクリプトの説明をします。cat $1 の $1 は コマンドmistumori.sh の 第一引数で mistumori.txt のことです。このようにシェルは $1 を第一引数 $2 を第二引数 $3 を第三引数 というように置換えします。またコマンドmistumori.shは $0 で置換えされ、 引数の数は $# で置き換えます。

% elvis hikisu.sh
#!/bin/sh
echo 'コマンド' $0
echo '第一引数' $1
echo '第二引数' $2
echo '第三引数' $3
echo '第四引数' $4
echo '第五引数' $5
echo '第六引数' $6
echo '第七引数' $7
echo '第八引数' $8
echo '第九引数' $9
echo '引数の数' $#

このようなファイルを作り chmod +x で実行権を与えます。

% ./hikisu.sh '蛇' '馬' '羊' '猿' '鳥' '犬' '猪' '鼠' '牛'
コマンド ./hikisu.sh
第一引数 蛇
第二引数 馬
第三引数 羊
第四引数 猿
第五引数 鳥
第六引数 犬
第七引数 猪
第八引数 鼠
第九引数 牛
引数の数 9

置換えできるのは9番目の引数までです。次に cat $1 の標準出力をパイプを通して awk -F \\ '{ print $2 }' に渡しています。-F はフィールドセパレータを\ バックスラッシュにしていします。\は意味のある記号なので\を前に付けて\自体を あらわします。Windowsからは\バックスラッシュは円マークに表示されます。

% cat mistumori.txt | awk -F \\ '{ print $2 }'
8,980  faith
10,970  faith
28,770  faith
4,570  faith
12,700  faith
12,570  faith
1,570  faith
27,700  faith

6,970  faith
29,680  pc-park
2,200  faith

セパレータを \ とすると mistumori.txt は \ の前と後ろの二つに分けることができます。 この後ろの部分を取り出すために awk -F \\ '{ print $2 }' の print $2 の部分です。 print $1 とすると前の部分が取り出されます。このように $1 は一番目の列 $2 は 二番目の列 $3 は三番目の列というふうに取り出すことができます。$0は全体を 取り出すことができます。セパレータの指定がないときは空白をセパレータとします。 次に tr -d , として , コンマを取り除きます。tr は置換えコマンドでDOSの改行 コードをUNIXの改行コードに変えたいときに重宝されるコマンドです。くわしくは こちら

% cat mistumori.txt | awk -F \\ '{ print $2 }' | tr -d ,
8980  faith
10970  faith
28770  faith
4570  faith
12700  faith
12570  faith
1570  faith
27700  faith

6970  faith
29680  pc-park
2200  faith

次にこの第一列目の数を awk で計算します。

% cat mistumori.txt | awk -F \\ '{ print $2 }' | tr -d , | awk ' { s = s + $1 } \
END { print s }'
146680

awk '{ s = s + $1 } END { print s }' で第一列目の数の合計を求めることが できます。s = s + $1 は s += $1 のように書くこともできます。\はコマンドが 長いために二行にするためです。今回のスクリプトでは printf で書式設定を しています。expr では小数点の計算はできませんが awk はできます。 s % 1000 の % は割った余りを求めるものです。printfで書式設定をする場合 書式の区切りには , コンマが付きます。このプログラムはバグありで awk -F \\ '{ print $2 }' で \ をセパレータとしていますが前半の文字列に よってうまく働かない時があるので注意が必要です。

``キーボード''の``ボ''があるとダメです。

参考文献

The GNU Awk User's Guide

awkの名前は Alfred V. Aho, Peter J. Weinberger, Brian W. Kernighan ら三人の 開発者の名前からきています。awkのオリジナルバージョンは1977年に AT&Tベル研究所 で書かれたそうです。

Last modified: Tue Apr 17 21:46:23 JST 2001