-->

2010-12-19

ffmpeg と flvtool2 でエラーになる例

FFmpeg version SVN-r25767 で作成した動画が flvtool2 でエラーになりました。
0.6_p25767 => 0.6 に戻しても使えるようになります。

$ cat /etc/redhat-release
CentOS release 5.5 (Final)

$ flvtool2 -UP tmp.flv
ERROR: EOFError
ERROR: /usr/lib/ruby/site_ruby/1.8/flv/amf_string_buffer.rb:37:in `read'
ERROR: /usr/lib/ruby/site_ruby/1.8/flv/video_tag.rb:80:in `read_header'
ERROR: /usr/lib/ruby/site_ruby/1.8/flv/video_tag.rb:47:in `after_initialize'
ERROR: /usr/lib/ruby/site_ruby/1.8/flv/tag.rb:56:in `initialize'
ERROR: /usr/lib/ruby/site_ruby/1.8/flv/stream.rb:449:in `new'
ERROR: /usr/lib/ruby/site_ruby/1.8/flv/stream.rb:449:in `read_tags'
ERROR: /usr/lib/ruby/site_ruby/1.8/flv/stream.rb:58:in `initialize'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2/base.rb:272:in `new'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2/base.rb:272:in `open_stream'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2/base.rb:238:in `process_files'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2/base.rb:225:in `each'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2/base.rb:225:in `process_files'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2/base.rb:44:in `execute!'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2.rb:168:in `execute!'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2.rb:228
ERROR: /usr/bin/flvtool2:2:in `require'
ERROR: /usr/bin/flvtool2:2

$ ffmpeg -y -i tmp.flv -vcodec copy -acodec copy tmp2.flv
FFmpeg version 0.6.1, Copyright (c) 2000-2010 the FFmpeg developers
  built on Dec  4 2010 15:35:31 with gcc 4.1.2 20080704 (Red Hat 4.1.2-48)
~中略~
frame= 6243 fps=  0 q=-1.0 Lsize=    9331kB time=204.04 bitrate= 374.6kbits/s
video:7493kB audio:1594kB global headers:0kB muxing overhead 2.688855%

$ flvtool2 -UP tmp2.flv
---
/tmp/tmp2.flv:
  hasKeyframes: true
  cuePoints:
  audiodatarate: 62.9997023152194
  hasVideo: true
  stereo: true
  canSeekToEnd: false
  framerate: 30
  audiosamplerate: 44000
  videocodecid: 7
  datasize: 9500370
  lasttimestamp: 208.274
  audiosamplesize: 16
  audiosize: 1726071
  hasAudio: true
  audiodelay: 0
  videosize: 7772385
  metadatadate: Sun Dec 19 22:37:09 GMT+0900 2010
  metadatacreator: inlet media FLVTool2 v1.0.6 - http://www.inlet-media.de/flvtool2
  lastkeyframetimestamp: 206.572
  height: 200
  filesize: 9556611
  hasMetadata: true
  keyframes:
    times:
      - 0
      - 0
      - 8.341
      - 9.375
      - 13.179
~中略~
      - 8720576
      - 8944857
      - 9162079
      - 9372005
      - 9548418
  audiocodecid: 2
  videodatarate: 295.906392540596
  duration: 208.307
  hasCuePoints: false
  width: 352
...

$ ffmpeg 2>&1 | head -n2
FFmpeg version 0.6, Copyright (c) 2000-2010 the FFmpeg developers
  built on Dec 19 2010 23:03:42 with gcc 4.4.4

$ ffmpeg -i src/a.flv -vcodec libx264 -vpre medium dst2/a.flv

$ flvtool2 -UP a.flv
---
/tmp/dst2/a.flv:
  hasKeyframes: true
  cuePoints:
  audiodatarate: 65.916396729909
  hasVideo: true
  stereo: true
  canSeekToEnd: false
  framerate: 30
  audiosamplerate: 11000
  videocodecid: 7
  datasize: 481161
  lasttimestamp: 12.966
  audiosamplesize: 16
  audiosize: 109639
  hasAudio: true
  audiodelay: 0
  videosize: 370742
  metadatadate: Sun Dec 19 23:07:46 GMT+0900 2010
  metadatacreator: inlet media FLVTool2 v1.0.6 - http://www.inlet-media.de/flvtool2
  lastkeyframetimestamp: 12.666
  height: 240
  filesize: 483766
  hasMetadata: true
  keyframes:
    times:
      - 0
      - 0
      - 8.333
      - 12.666
    filepositions:
      - 763
      - 824
      - 273615
      - 471023
  audiocodecid: 2
  videodatarate: 226.093475242943
  duration: 12.999
  hasCuePoints: false
  width: 320
...


# 使えない。
$ ffmpeg 2>&1 | head -n2
FFmpeg version SVN-r25767, Copyright (c) 2000-2010 the FFmpeg developers
  built on Dec 19 2010 23:17:31 with gcc 4.4.4

# 使える。
$ ffmpeg 2>&1 | head -n2
FFmpeg version 0.6, Copyright (c) 2000-2010 the FFmpeg developers
  built on Dec 19 2010 23:03:42 with gcc 4.4.4

# 使える。
$ ffmpeg 2>&1 | head -n2
FFmpeg version 0.6.1, Copyright (c) 2000-2010 the FFmpeg developers
  built on Dec  4 2010 15:35:31 with gcc 4.1.2 20080704 (Red Hat 4.1.2-48)

2010-11-21

duplicate claimed blocks

e2fsck -y -c -f -D -v を実行して再起動したところ、
duplicate claimed blocks と出るので再度実行したところ、
ファイルがリネームされている例です。

$ sudo mv /etc/make.profi~0 /etc/make.profile
$ cat /etc/profile.env
...バイナリデータ...
$ sudo env-update && source /etc/profile
$ sudo mv /etc/sandbox.co~0 /etc/sandbox.conf

沢山リネームされています。
$ sudo find / -name "*~0" > find.errorFile.txt 2>&1 &
/etc/profile.en~0
/etc/make.conf~0
/etc/networ~0
/etc/mt~0
/etc/gnome-vfs-mime-mag~0
/etc/ld.so.cach~0
...
/usr/sbin/rd~0
/usr/sbin/zabbix_age~0
/usr/sbin/genspr~0
/usr/sbin/pluginview~0
/usr/sbin/addgnupgho~0
/usr/sbin/mysqlmanag~0
/usr/sbin/groupa~0
/usr/sbin/vi~0
/usr/sbin/pw~0
/usr/sbin/newuse~0
/usr/sbin/kpropl~0
/usr/sbin/htdige~0
/usr/sbin/mklost+fou~0
/usr/sbin/postki~0
/usr/sbin/quickp~0
/usr/sbin/sendma~0
/usr/sbin/krb5-send-~0
/usr/sbin/uuserv~0
/usr/sbin/groupd~0
...

エラーを手動で修正しつつパッケージを再インストールします。
$ sudo emerge -e system など

2010-11-06

javascript-mode

emacs の 23.1 => 23.2 で javascript-mode がうまく動かない場合の例です。

結論は javascript.el の場合に直接呼ぶか、
js.el の場合に js-mode-hook を使うかの違いです。
app-emacs/javascript はマスクされているので問題なければ js.el が良いです。
(load "/usr/share/emacs/site-lisp/javascript/javascript.el")
or
javascript-mode-hook => js-mode-hook

以下は詳細です。

よく見るとモード自体が違います。
(JavaScript) => (Javascript)
$ grep mode-name /usr/share/emacs/site-lisp/javascript/javascript.el
  (setq mode-name "JavaScript")
$ grep mode-name /usr/share/emacs/23.2/lisp/progmodes/js.el
  (setq mode-name "Javascript")

$ eix ^javascript$ -cI
[D] app-emacs/javascript (2.2.1@2010年11月06日 -> ~2.2.1): Major mode for editing JavaScript source text
$ equery files javascript|grep javascript.el
/usr/share/emacs/site-lisp/javascript/javascript.el
$ find /usr/share/emacs/ -name js.el
/usr/share/emacs/23.2/lisp/progmodes/js.el

$ equery belongs /usr/share/emacs/23.2/lisp/progmodes/js.el
[ Searching for file(s) /usr/share/emacs/23.2/lisp/progmodes/js.el in *... ]
app-editors/emacs-23.2 (/usr/share/emacs/23.2/lisp/progmodes/js.el)

js-indent-tabs-mode ぽい設定が無いです。
$ grep defcustom /usr/share/emacs/23.2/lisp/progmodes/js.el
...

(setq js-indent-level 16) ;; 本当に有効かどうか見たい。

javascript-mode-hook が 23.2 で動かないです。
名前が違います。
(add-hook 'js-mode-hook
          (function
           (lambda ()
             (setq indent-tabs-mode nil)
             )))

タブの利用を無効にしているだけの場合 js.el で問題ないと思います。
/* ... */ のコメントのインデントと、複数の入れ子の括弧だけのインデントがまともになったような気がします。

e2fsck をローカルのコンソールから使う例

http://beau.org/pipermail/whitebox-users/2005-April/006009.html
http://www.goudkov.com/public/articles/changing_distro.jsp

$ export LANG=C
$ export LC_ALL=C
$ init 1
$ mount -o remount,ro /
mount: / is busy
$ lsof|grep txt
$ killall screen
$ mount -o remount,ro /
$ mount | less
$ touch /test.txt
touch: cannot touch `/test.txt': Read-only file system
$ e2fsck -y -c -f -D -v /dev/cobd0 2>&1 1>/dev/shm/e2fsck.cobd0.log
$ mount -o remount,rw /
$ cp -pi /dev/shm/e2fsck.cobd0.log ~
$ runlevel
3 1
$ init 3

上の例はext4だが、別のパソコンの普通のハードディスク上のext4で実行したら、
エラー無しで終了したものの、再起動時にduplicate claimed blocksとなったので、
上の例だと何かが悪い。

追記: mount -o remount,rw / の前に sync; sync; sync; を行う。関係ないかもしれない。

2010-11-01

xdm => gdm

http://www.nbrains.net/php/pukiwiki/index.php?Setup%2FPC-XServer

$ diff /etc/conf.d/xdm.2010-11-01 /etc/conf.d/xdm
16c16
< DISPLAYMANAGER="xdm"
---
> DISPLAYMANAGER="gdm"
$ diff /etc/X11/gdm/custom.conf.2010-11-01 /etc/X11/gdm/custom.conf
59a60,61
> Enable=true
> Port=177

2010-10-23

sys-apps/groff-1.20.1-r1 の設定

http://d.hatena.ne.jp/kei10in/20091019/1255980903

$ eix -I groff
[I] sys-apps/groff
Available versions:  1.20.1-r1 ~1.20.1-r2 ~1.20.1-r3 {X examples linguas_ja}
Installed versions:  1.20.1-r1(23時28分43秒 2010年10月22日)(-X -examples -linguas_ja)
Homepage:            http://www.gnu.org/software/groff/groff.html
Description:         Text formatter used for man pages

$ man groff 2>&1 | grep -nPi "utf8|\\-[TD]"
10:             [ -Fdir ] [ -Idir ] [ -Tdev ] [ -ffam ] [ -Mdir ] [ -dcs ]
33:       utf8   UTF-8    エンコーディングの     Unicode     (ISO     10646)     文字集合を利用する
59:       -t     tbl を使って前処理を行います。
93:       -Tdev  デバイス dev 用に出力します。デフォルトのデバイスは ps です。
97:              Print アクションを実行させます。 -Tps 以外が指定されている場合は、よい結果が得られません。
115:       -dcs
155:       EBCDIC ホストにおいては、出力デバイス ascii, latin1, utf8 は使用不可です。 同様に、 cp1047 は ASCII
162:              groff -mandoc -Tlatin1 foo.1 | less
166:              groff -m mandoc -Tlatin1 foo.1 | less
$ groff -h | grep -Pi "^\\-[DkT]|encoding"
-k      preprocess with preconv
-t      preprocess with tbl
-Tdev   use device dev
-dcs    define a string c as s
-Karg   use arg as input encoding.  Implies -k
-Darg   use arg as default input encoding.  Implies -k
$ man preconv 2>&1 | grep -ni euc
108:              big5, cp1047, euc-jp, euc-kr, gb2312, iso-8859-1, iso-8859-2,
115:              ascii, chinese-big5, chinese-euc, chinese-iso-8bit, cn-big5,
117:              cyrillic-iso-8bit, cyrillic-koi8, euc-china, euc-cn, euc-japan,
118:              euc-japan-1990, euc-korea, greek-iso-8bit, iso-10646/utf8,
120:              iso-latin-7, iso-latin-9, japanese-euc, japanese-iso-8bit, jis8,
121:              koi8, korean-euc, korean-iso-8bit, latin-0, latin1, latin-1,
$ grep ^JNROFF /etc/man.conf
JNROFF          /usr/bin/nkf -e | /usr/bin/groff -Deuc-jp -Tutf8 -mandoc
$ man ls 2>&1 | nkf -g
UTF-8
$ man useradd 2>&1 | nkf -g
UTF-8

よく見ると横幅がオーバーしているのに、文字の間に隙間があります。
groff を新しくして groff-1.19 の設定にしたところ、動きました。
cjk => linguas_ja になっていて groff-1.20.1-r1 の時には設定をしても off でした。
$ sudo ACCEPT_KEYWORDS="~x86" emerge -av sys-apps/groff
...
$ eix groff
[D] sys-apps/groff
     Available versions:  1.20.1-r1 ~1.20.1-r2 ~1.20.1-r3 {X examples linguas_ja}
     Installed versions:  1.20.1-r3(15時18分07秒 2010年10月23日)(linguas_ja -X -examples)
     Homepage:            http://www.gnu.org/software/groff/groff.html
     Description:         Text formatter used for man pages

$ grep ^JNROFF /etc/man.conf
JNROFF          /usr/bin/nkf -e | LANG=ja_JP.EUC-JP LC_ALL=ja_JP.EUC-JP /usr/bin/groff -Tnippon -mandocj | /usr/bin/nkf -w

$ grep -i linguas /etc/make.conf
LINGUAS="ja"

manコマンド自体の日本語がEUC-JPの場合の修正の例1。英語にする。
$ echo "sys-apps/man -nls" >> /etc/portage/package.use

manコマンド自体の日本語がEUC-JPの場合の修正の例2。エラー出力をutf8にする。
$ alias man='LANG=C LC_ALL=C /usr/bin/man'
$ cat /usr/local/bin/jaman
#!/bin/sh
# http://www.netfort.gr.jp/~tomokuni/lms/shell/text/shell3.txt
# 1.2  標準エラー出力のみをパイプ => (例 3) => を適用

BUF="`LANG=ja_JP.UTF-8 LC_ALL=ja_JP.UTF-8 /usr/bin/man $@ 3>&1 1>&2 2>&3 3>&-`"
RET="$?"
if [ -n "$BUF" ]; then
    echo "$BUF" | nkf -w 1>&2
    if [ "$RET" -eq 0 ]; then
        echo
    fi
fi
exit "$RET"
$ jaman
どのマニュアルを表示しますか?
$ jaman xxx
xxx のマニュアルはありません。
$ jaman -h
man, バージョン 1.6f
...

2010-10-19

revdep-rebuild --library libcrypto.so.0.9.8

システムを更新したら下記のようなメッセージが表示される。
...
 *   # revdep-rebuild --library libcrypto.so.0.9.8
 *   # revdep-rebuild --library libssl.so.0.9.8
...
 *   # rm '/usr/lib/libcrypto.so.0.9.8'
 *   # rm '/usr/lib/libssl.so.0.9.8'
...

検索してもわからないパッケージ名でエラーになった。
xxx/-MXXXX-libpq のようなイメージだった。
$ revdep-rebuild --library libcrypto.so.0.9.8
1...
2...
3...
4...
xxx のパッケージが無い、というエラーになる。

手動で xxx の行を削除すると revdep-rebuild --library libcrypto.so.0.9.8 は動作した。
$ grep xxx /var/cache/revdep-rebuild/*.rr

原因は システムの管理外の libcrypto.so.0.9.8 を利用するライブラリだった。
手動で削除した。
$ equery belongs /usr/lib/libpq*
[ Searching for file(s) /usr/lib/libpq-4.a,/usr/lib/libpq.a,/usr/lib/libpq.so,/usr/lib/libpq.so.4,/usr/lib/libpq.so.4.1 in *... ]
$ ll /usr/lib/libpq*
-rw-r--r-- 1 root root 153970 2009-10-30 21:17:47 /usr/lib/libpq-4.a
lrwxrwxrwx 1 root root      9 2009-10-30 21:17:53 /usr/lib/libpq.a -> libpq-4.a
lrwxrwxrwx 1 root root     12 2009-10-30 21:17:53 /usr/lib/libpq.so -> libpq.so.4.1*
lrwxrwxrwx 1 root root     12 2009-10-30 21:39:47 /usr/lib/libpq.so.4 -> libpq.so.4.1*
-rwxr-xr-x 1 root root 114364 2009-10-30 21:17:47 /usr/lib/libpq.so.4.1*
$ sudo rm -f /usr/lib/libpq*

2010-10-11

pcntl_fork の例

子プロセスを作成する例です。
myDaemon.2010-10-11.tar.gz をダウンロードします。
設定の変更と子プロセスの内容の変更は myDaemon.php です。
起動方法の例です。
$ php myDaemon.php
$ tail -f /tmp/myDaemon.child_log
...
$ kill -TERM `cat /tmp/myDaemon.pid` # 止まる。
$ kill -USR1 `cat /tmp/myDaemon.pid` # 子プロセスの終了を待って止まる。
$ kill -HUP -`cat /tmp/myDaemon.pid` # ログファイルを再度開く。子プロセスも開く。

説明です。
<?php

// シグナルを受け取るのに必要です。
declare(ticks = 1);

// クラスをロードします。
require_once("class.myDaemonBase.php");

// クラスの設定を変更します。
class myDaemon extends myDaemonBase
{
    // 親プロセスのPIDの保存先
    protected $pidFile         = "/tmp/myDaemon.pid";
    // 親プロセスのログの保存先
    protected $mainLogFile     = "/tmp/myDaemon.log";
    // 子プロセスのログの保存先
    protected $childLogFile    = "/tmp/myDaemon.child_log";
    // phpエラーをフックする前に出るphpエラーの保存先
    protected $phpErrorLogFile = "/tmp/myDaemon.php_error_log";
    // 子プロセスの数
    protected $maxChildNum     = 10;
    // 無限にループする部分で1回ごとに休憩する秒数
    protected $sleepTime       = 1;
    // ログを増やすかどうか?
    protected $debugFlag       = false;
}

// 子プロセスが実行する関数名
function childProcess($class)
{
    $class->Logger("Start child process");
    $time = rand(1, 60);
    $class->Logger("Sleep for {$time} seconds.");
    for ($i = 0; $i < $time; $i++)
    {
        sleep(1);
    }
    $class->Logger("End child process");
}

// 常駐プロセスの起動
myDaemon::start();
exit(0);

メモリの設定が足りていないと子プロセスの生成と終了を繰り返す例です。
$ cat /etc/php/cli-php5/php.ini | grep -v ^\; | grep -v ^$ > myDaemon.ini
$ emacs myDaemon.ini
$ cat myDaemon.ini
short_open_tag                 = Off
allow_call_time_pass_reference = Off
memory_limit                   = 8M
error_reporting                = E_ALL
display_errors                 = STDERR
log_errors                     = On
error_log                      = /tmp/myDaemon.php_error_log
log_errors_max_len             = 4096
register_long_arrays           = Off
include_path                   = ".:/usr/share/php5:/usr/share/php"
enable_dl                      = Off
allow_url_fopen                = Off

extension = pcntl.so
extension = mbstring.so

mbstring.language             = Japanese
mbstring.internal_encoding    = UTF8
mbstring.http_input           = auto
mbstring.http_output          = pass
mbstring.encoding_translation = On
mbstring.detect_order         = auto
mbstring.substitute_character = 0x3013
mbstring.func_overload        = 0
$ php -n -c myDaemon.ini myDaemon.php
$ sleep 3
$ kill `cat /tmp/myDaemon.pid`
$ tail -n1 /tmp/myDaemon.php_error_log
[17-Oct-2010 01:51:37] PHP Fatal error:  Allowed memory size of 8388608 bytes exhausted (tried to allocate 10485761 bytes) in /var/www/localhost/php/System_Daemon/myDaemon.php on line 26
狙いは動的にロードするモジュールを最低限にすること、
設定の変更を、変更したい部分だけに絞ってわかりやすくすること、です。

例えば、変更したことによってプログラムが memory_limit=8M 以上ないと動かない、
などのハードウェィアへの依存度がわかったり、
phpのバグだと認識していたものが、ただの設定の違いであることが判明したり、
するかもしれません。

よって例えば centos5 の php5.1.6 のデフォルトがあなたの利用する全てのphpである場合、
このような設定の変更は、混乱するだけです。

php -n は /etc/php.ini などを全て読みません。
php -c ファイル名は、設定ファイルを追加で読みます。
php5.2より新しくないと -n と -c は同時に使えないかもしれません。

error_reporting = E_ALL はお勧めです。
バグが必ずあるとして E_NOTICE を発生させるタイプは、すぐに対応できる、というのが主な理由です。
E_NOTICE が邪魔というのは、すぐになれる可能性が高いです。(正常な場合に出ないように書くのは容易という意味です。)
対して E_NOTICE が発生するミスというのはログに取れないと特定が大変です。
デフォルトが E_ALL & ~E_NOTICE であると仮定した場合の話です。
例えば perl で use strict; use warnings; があった場合に少し安心しますが、それに似ています。
log_errors=On, error_log=filename, display_errors=0|1|stderr もセットで有効です。

2010-09-27

e2fsck の例

mount したまま実行した場合は、きっと、おかしくなります。
/ など umount できない場合には、別の linux を立ち上げる必要があります。
cd などの linux の場合、あまり古い CD だと CD の物理的な劣化やソフトウェアが古いため、後悔する場合があります。
お使いのデストリビューションの最新の CD のレスキューモードであれば良いかもしれません。
バックアップが取れる場合は、必ず取る、mount できない場合でも dd で取る、
バックアップが取れない場合は行わない or 覚悟する、
といった対策を行います。
$ dd if=/dev/DEV bs=512 conv=sync,noerror 2>/var/tmp/dd.DEV.err | gzip 2>/var/tmp/dd.DEV.gzip.err 1>/var/tmp/dd.DEV.out.gz
/tmp/のサイズが小さいとエラーになる場合があります。
cat: write error: No space left on device
cat: 書き込みエラー: デバイスに空き領域がありません
ssh経由でも大体同じです。
$ ssh 192.168.0.100 "sudo dd if=/dev/md124 bs=512 conv=sync,noerror" 2>/var/tmp/dd.md124.err | gzip 2>/var/tmp/dd.md124.gzip.err 1>/var/tmp/dd.md124.out.gz
バックアップが成功しているかどうかを確認したほうが良いです。
$ ll -h /var/tmp/dd.md124.*
-rw-r--r-- 1 xxx xxx  94 2010-09-27 03:53:01 /var/tmp/dd.md124.err
-rw-r--r-- 1 xxx xxx   0 2010-09-27 03:51:46 /var/tmp/dd.md124.gzip.err
-rw-r--r-- 1 xxx xxx 93M 2010-09-27 03:53:01 /var/tmp/dd.md124.out.gz
$ cat /var/tmp/dd.md124.err
513792+0 records in
513792+0 records out
263061504 bytes (263 MB) copied, 71.2668 s, 3.7 MB/s

(例) linux の場合
$ cd /tmp
$ gunzip dd.md124.out.gz
$ mkdir boot
$ sudo mount -o loop -r dd.md124.out /tmp/boot/
$ mount | grep dd.md124.out
/tmp/dd.md124.out on /tmp/boot type ext2 (ro,loop=/dev/loop0)
$ ls -alR /tmp/boot/
...

(例) windows の colinux の場合
# cobd5=D:\coLinux\gentoo\dd.md124.out を追加して再起動
$ sudo mount -r /dev/cobd5 /mnt/gentoo/
$ mount | grep /dev/cobd5
/dev/cobd5 on /mnt/gentoo type ext2 (ro)
$ ls -alR /mnt/gentoo/
...

マニュアルを読む。
$ man e2fsck

エラーあってもほっとく
$ e2fsck -n /dev/DEV
エラー比較的に安全なのは自動でyes
$ e2fsck -p /dev/DEV
ダメかもしれないが全部yes
$ e2fsck -y /dev/DEV

badblocks を安全に使いたい
$ e2fsck -p -c /dev/DEV
全部の場所をチェック
$ e2fsck -p -c -f /dev/DEV
ディレクトリ最適化
$ e2fsck -p -c -f -D /dev/DEV
詳細を表示
$ e2fsck -p -c -f -D -v /dev/DEV

バックグラウンドの場合-yに変更
$ e2fsck -y -c -f -D -v /dev/DEV 2>&1 1>/var/tmp/e2fsck.DEV.log &
$ tail -f /var/tmp/e2fsck.DEV.log

ハードディスクの交換の例

HD103SI の2台で raid1 だったのが /proc/mdstat の md4 が [_U] で sda4 が外れており、
sda の該当箇所を dd で読み込みできないことを確認してから書き込み(3~4箇所)、
add したところ sdb の xxx セクタが読めないというエラーで [UU] の状態にできないので、
0S02601 を2台買ってきて取り付ける例です。

不良セクタを探す。
$ sudo smartctl --test=short /dev/sda
$ sudo smartctl --test=long /dev/sda
不良セクタがある場合。(smartctl の test は、しばらく時間がかかります。)
$ sudo smartctl -a /dev/sda
# 1  Extended offline    Completed: read failure       90%      7342         1157047143
# 2  Short offline       Completed: read failure       20%      7342         1157047143
ある程度、不良セクタを読み込む。
$ sudo dd if=/dev/sda of=/tmp/abc.txt bs=512 count=1 skip=1157047143
$ sudo dd if=/dev/sda of=/tmp/abc.txt bs=512 count=1 skip=1157047143
$ sudo dd if=/dev/sda of=/tmp/abc.txt bs=512 count=1 skip=1157047143
$ sudo dd if=/dev/sda of=/tmp/abc.txt bs=512 count=1 skip=1157047143
$ sudo dd if=/dev/sda of=/tmp/abc.txt bs=512 count=1 skip=1157047143
読み込めない場合、不良セクタに書き込む。(その前にバックアップを取る。)
$ sudo dd if=/dev/zero of=/dev/sda bs=512 count=1 seek=1157047143
不良セクタを探す、に戻る。

sda(HD103SI) の数箇所を /dev/zero で上書きした後の状態の例です。
195番の数字がとても多いのが特徴です。
sdb(HD103SI) も同じぐらいの桁に見える195番の量でした。
sda の Reallocated_Sector_Ct が0のままでした。
$ sudo smartctl -a /dev/sda|grep -iP "^\s*(5|19[5678])|error.*count"
  5 Reallocated_Sector_Ct   0x0033   100   100   010    Pre-fail  Always       -       0
195 Hardware_ECC_Recovered  0x001a   100   100   000    Old_age   Always       -       2533423135
196 Reallocated_Event_Count 0x0032   100   100   000    Old_age   Always       -       0
197 Current_Pending_Sector  0x0012   100   100   000    Old_age   Always       -       0
198 Offline_Uncorrectable   0x0030   100   100   000    Old_age   Offline      -       0
199 UDMA_CRC_Error_Count    0x003e   100   099   000    Old_age   Always       -       2
    5        0        0  Not_testing
sdb に sda と同じ方法を試したところ、読み込みも書き込みもできなかったので諦めました。
また sdb の Reallocated_Sector_Ct が0のままでした。

sda(HD103SI) => sda(0S02601) に交換する。
sda にパーテーションを作成する。
livecd ~ # fdisk -l /dev/sdb

Disk /dev/sdb: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x0005eba9

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1          32      257008+  fd  Linux raid autodetect
/dev/sdb2              33        1978    15631245   fd  Linux raid autodetect
/dev/sdb3            1979        5869    31254457+  fd  Linux raid autodetect
/dev/sdb4            5870      121601   929617290   fd  Linux raid autodetect
livecd ~ # fdisk -l /dev/sda

Disk /dev/sda: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xe4c289be

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1               1          32      257008+  fd  Linux raid autodetect
/dev/sda2              33        1978    15631245   fd  Linux raid autodetect
/dev/sda3            1979        5869    31254457+  fd  Linux raid autodetect
/dev/sda4            5870      121601   929617290   fd  Linux raid autodetect

1番細かい単位でコピーする。
bootセクタに書き込まないと、新しい HDD が sda の場合、起動しないので grub で書き込む。
dd if=/dev/sdb of=/dev/sda bs=512 conv=sync,noerror
bs を大きくしたい場合は man dd などを読んだほうが良いです。
$ sudo dumpe2fs /dev/DEV | grep "^Block size:"

大量にエラーが出ていたので sdb の方がもっとおかしかったかもしれない。
Mon Sep 20 18:00:49 UTC 2010
dd: reading `/dev/sdb': Input/output error
1156476160+0 records in
1156476160+0 records out
592115793920 bytes (592 GB) copied, 44934.5 s, 13.2 MB/s

... (1156476160+1 ~ 1156476160+478)

592116038656 bytes (592 GB) copied, 45157.6 s, 13.1 MB/s
dd: reading `/dev/sdb': Input/output error
1156476160+479 records in
1156476639+0 records out
592116039168 bytes (592 GB) copied, 45157.6 s, 13.1 MB/s
1953524688+480 records in
1953525168+0 records out
1000204886016 bytes (1.0 TB) copied, 98823 s, 10.1 MB/s
Tue Sep 21 21:27:52 UTC 2010

sdb(HD103SI) => sdb(0S02601) に交換する。
なんだかんだで起動する。
fdiskでsdbにパーテーションを作成する。
mdadm -add して /proc/mdstat で確認する。
(例) watch -n60 cat /proc/mdstat
なんだかんだで成功しました。

ついでに ext4 にする。(失敗した場合、同じ手順で復帰できると考えているためです。)
install-amd64-minimal-20100902.iso をdvdで用意する、などの別の linux を用意する。
tune2fs -O has_journal,dir_index,filetype,extent,flex_bg,sparse_super,large_file,huge_file,uninit_bg,dir_nlink,extra_isize /dev/mdXXX
tune2fs -I 256 /dev/mdXXX
e2fsck -y /dev/mdXXX
md1~md4 が md124~md127 になっていたが変更方法がわからないので、
/etc/fstab と /etc/mdadm.conf を修正する。
resize_inode が無い場合で Inode size: 128 の場合 256 にできないかもしれません。
$ sudo dumpe2fs /dev/DEV | grep "^Inode size:"

カーネルに対応が無いと読めません。
$ grep -i ext4 /etc/kernels/kernel-config-x86_64-2.6.34-gentoo-r6
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_XATTR=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
# CONFIG_EXT4_DEBUG is not set

grub-0.97-r10 で ext4 が読めましたが、やる前に確認するべきです。
$ eix ^grub$
[I] sys-boot/grub
     Available versions:  *0.92-r1 0.94-r1 0.96-r1 0.96-r2 ~0.96-r3 ~0.97 0.97-r2 0.97-r3 0.97-r4 0.97-r5 0.97-r6 ~0.97-r8 0.97-r9 0.97-r10 **1.98 **9999 {custom-cflags debug multislot ncurses netboot static truetype}
     Installed versions:  0.97-r10(22時19分03秒 2010年08月06日)(ncurses -custom-cflags -netboot -static)
     Homepage:            http://www.gnu.org/software/grub/
     Description:         GNU GRUB 2 boot loader

grub の起動オプションを変更しました。
番号が変わると面倒なので変えない方法を探した方が良かったです。
$ grep md126 /boot/grub/grub.conf
kernel /boot/kernel-genkernel-x86_64-2.6.34-gentoo-r6 root=/dev/ram0 init=/linuxrc ramdisk=8192 udev domdadm real_root=/dev/md126

今回の例は、7月上旬に、
SMART error (CurrentPendingSector) detected on host: xxx
というメールが来ていたのを放置して、
9月に入った頃には md4 が [_U] だったようだが、
さらに放置した場合に発生する場合が有ります。

また放置気味な場合ソフトウェアraid1は3台が良いかもしれません。
交換して mdadm --add しても残っている方もおかしい場合があるためです。

またbootセクタの書き込みを忘れると、それがsdaの場合は起動しません。
また /, /boot などのOSの起動に関わる部分を ext4 に変更する場合は、下調べした方が良いです。

また swap はメモリの2倍で 16GB 取りましたが使ってないです。
設置しないか 1~2GB 程度で良かったかもしれません。
また寿命が縮んだ原因は md4 に kvm のイメージをサイズ可変のフォーマットで設置したため、かもしれません。
md1 => 256MB, /boot
md2 => 16GB , swap
md3 => 30GB , /
md4 => 残り , /mnt/share

また ext4 に変更した場合の利点の内の一つは
$ sudo du -sh /*
などが早くなったかもしれません。
また e2fsck が早くなっているらしいです。
またオンラインデフラグが今後あるらしいですが、まだ無いです。

また、一応インストール時と同じ手順でmdデバイスの番号を戻せます。
install-amd64-minimal-20100902.isoからブート。
boot: [Enter]
jp [Enter]

sshdを起動。
$ /etc/init.d/sshd start
$ passwd
root [Enter]
root [Enter]
$ ifconfig

sshクライアントでログイン。
$ ssh 192.168.0.4
login as: root [Enter]
password: root [Enter]

raidを止める。
$ mdadm --misc --stop /dev/md124
$ mdadm --misc --stop /dev/md125
$ mdadm --misc --stop /dev/md126
$ mdadm --misc --stop /dev/md127

raidを作成する。メッセージを読む。種類の指定に注意する。
$ mdadm --create /dev/md1 --level=1 --raid-devices=2 /dev/sda1 /dev/sdb1
$ mdadm --create /dev/md2 --level=1 --raid-devices=2 /dev/sda2 /dev/sdb2
$ mdadm --create /dev/md3 --level=1 --raid-devices=2 /dev/sda3 /dev/sdb3
$ mdadm --create /dev/md4 --level=1 --raid-devices=2 /dev/sda4 /dev/sdb4

マウントする。
$ mount /dev/md3 /mnt/gentoo/
$ mount /dev/md1 /mnt/gentoo/boot/
$ mount /dev/md4 /mnt/gentoo/mnt/share/

デバイスをマウントする。
$ mount -t proc none /mnt/gentoo/proc
$ mount -o bind /dev /mnt/gentoo/dev

chrootでログインする。
$ chroot /mnt/gentoo /bin/bash
$ env-update
$ source /etc/profile
$ export PS1="(chroot) $PS1"

設定ファイルを作成する。
$ mdadm --detail --scan > /etc/mdadm.conf
# md124 => md1 などに戻す。
$ vi /etc/fstab

再起動する。DVDは外す。
$ exit
$ reboot

●ルートディレクトリの指定をする。
/dev/md3 [Enter]

●ログインして修正する。
$ sudo mount /boot/
$ cd /boot/grub/
$ sudo vi grub.conf
$ diff grub.conf.2010-10-02 grub.conf
13c13
< kernel /boot/kernel-genkernel-x86_64-2.6.34-gentoo-r6 root=/dev/ram0 init=/linuxrc ramdisk=8192 udev domdadm real_root=/dev/md126
---
> kernel /boot/kernel-genkernel-x86_64-2.6.34-gentoo-r6 root=/dev/ram0 init=/linuxrc ramdisk=8192 udev domdadm real_root=/dev/md3
$ sudo grub
grub > device (hd0) /dev/sda
grub > root (hd0,0)
grub > setup (hd0)
grub > device (hd0) /dev/sdb
grub > root (hd0,0)
grub > setup (hd0)
grub > quit

再起動してルートディレクトリを聞かれなければ/dev/sdaに書いたgrubの設定が反映されています。
$ ll /dev/md*
brw-rw---- 1 root disk 9, 1 2010-10-03 09:06:47 /dev/md1
brw-rw---- 1 root disk 9, 2 2010-10-03 09:06:45 /dev/md2
brw-rw---- 1 root disk 9, 3 2010-10-03 09:06:46 /dev/md3
brw-rw---- 1 root disk 9, 4 2010-10-03 09:06:47 /dev/md4

参考
http://www.gentoo.org/doc/ja/gentoo-x86-tipsntricks.xml?style=printable#software-raidhttp://www.gentoo.org/doc/ja/gentoo-x86-tipsntricks.xml?style=printable#software-raid
http://nabe.blog.abk.nu/0301
http://www.gentoo.org/doc/ja/handbook/handbook-x86.xml?part=1&chap=6#doc_chap1

2010-07-25

/etc/updatedb.conf の修正の例

バックアップのディレクトリを除外できていなかった。
 # Paths which are pruned from updatedb database
-PRUNEPATHS="/tmp /var/tmp /root/.ccache"
-PRUNEPATHS="${PRUNEPATHS} /var/cache /mnt/share/backup"
+PRUNEPATHS="/tmp /var/tmp /root/.ccache /var/cache /mnt/share/backup"

2010-07-16

dev-libs/gmp の再インストールの例

閲覧
$ lv /var/lib/portage/world

削除
$ sudo emerge -Cav dev-libs/gmp

エラーになる。
$ sudo emerge --update --deep --newuse --verbose --tree --with-bdeps=y --ask world

バイナリのインストール
$ sudo PORTAGE_BINHOST=http://tinderbox.dev.gentoo.org/default-linux/x86/ emerge -avgK dev-libs/gmp

PORTAGE_BINHOSTは
$ grep ^CHOST /etc/make.conf
CHOST="i686-pc-linux-gnu"
の場合。

再インストール
$ sudo emerge --oneshot -av dev-libs/gmp

確認
$ equery belongs dev-libs/gmp

手動で削除(--oneshotを付け忘れた場合)
$ sudo vi /var/lib/portage/world

http://tinderbox.dev.gentoo.org/default-linux/x86/dev-libs/
http://theoutsideofparr.blogspot.com/2009_05_01_archive.html

2010-07-11

my.cnfの追記の例

[mysql]
デフォルトの文字コード
default-character-set=utf8
タブで入力の補完。ディストリによってはデフォルト (mysql -u xxx --no-auto-rehash で確認)
auto-rehash

[mysqld]
デフォルトの文字コード
default-character-set=utf8
必ずutf8のデータが来る場合。こないとバックアップ、リストア時に悲惨かもしれない。
SELECT CHAR_LENGTH('全角の文字'); がおかしいが気にしない場合 default-character-set=binary をいろんな[xxx]に書いとけば良い。文字列関連がおかしくてもいいのであれば早くなるかもしれない。
skip-character-set-client-handshake
例えばもし5.0.xxの低いバージョンから5.0.xxの高いバージョンにアップしてリストアできなくなり、実はlatin1のテーブルにutf8,sjis,eucjpなどのlatin1以外を入れていたぜ、ということであれば、該当する低いバージョンのソースかrpmなどを探して他のどこかにインストールしてリストアして成功して再度binary指定でバックアップして、などやれば助かるかもしれません。
例えば、
show create table tablename;
 CREATE TABLE `tablename` ... CHARSET=latin1
であれば特に文字コードについてマニュアルを読むべきです。
latin1は特殊な値ではなく文字コードなので、例えばsjisをeuc-jpとして扱うと文字化けするのと同じようなミスです。
関係ないですが
http://www.php.net/manual/ja/function.mysql-set-charset.php
注意: 文字セットを変更するにはこの方法を使うことを推奨します。 mysql_query() で SET NAMES .. を実行する方法はお勧めできません。
どこかでsjisのバックスラッシュに関するドライバの設定云々と読んだような気がします。
//mysql_query("set names xxx");
mysql_set_charset("xxx");

/var/lib/mysqlのディレクトリを変更
datadir = /mnt/share/mysql
CREATE TABLE ... ENGINE=InnoDB ... 指定無しのデフォルト値
default_table_type = innodb
datadirのbinlogを10日後に消す
expire_logs_days = 10

接続数
max_connections = 80
管理(rootなど)用に残す
max_user_connections = 72
mysqlの中のプロセスの作成が再利用される。
thread_cache_size = 32
普通のアプリのタイムアウト。バッチ処理の場合に伸ばす。SET wait_timeout=86400;SET GLOBAL と書くと変えられる場合は戻さないとずっとそのままです。
wait_timeout = 30
SQL文の長さのMAX
net_buffer_length = 16K

myisam用の重要な値。msqyl専用のmyisam専用のサーバーの場合 5~9割
key_buffer_size = 128M
テーブルごとのfopenの保存する数。1024以上の場合制限解除(/etc/security/limits.conf). 1ユーザー1テーブルとかの場合、リリース後であれば祈る。
table_cache = 256
たぶんmyisamのselect専用のキャッシュ
query_cache_size = 32M

index無しソート
sort_buffer_size = 8M
myisam用?
myisam_sort_buffer_size = 8M
ランダムリード
read_rnd_buffer_size = 4M
連続リード
read_buffer_size = 4M
index無しjoin
join_buffer_size = 2M

内部データ。エラーがログに出る。増やす。出る。増やす。
innodb_additional_mem_pool_size = 16M
重要な値。msqyl専用のinnodb専用のサーバーの場合 5~9割
innodb_buffer_pool_size = 2048M
テーブルのファイルばらばら。管理の利点、サイズ増えすぎない。
innodb_file_per_table = true
commit時にディスク書き込み
innodb_flush_log_at_trx_commit = 1
バッファリングの重複をoff
innodb_flush_method = O_DIRECT
ログのメモリ
innodb_log_buffer_size = 16M
ログのファイル (/var/lib/mysql/ib_logfile0,1)バージョンによって変更後にリスタートでエラーor変化しない。変化させたい場合は消してからリスタート。
innodb_log_file_size = 64M
ログのファイル数 (/var/lib/mysql/ib_logfile0,1)
innodb_log_files_in_group = 2

手順
http://dsas.blog.klab.org/archives/50860867.html
mymemcheck を鵜呑みにする。
http://linux.mini13i.gotdns.org/?MySQL%2F%BA%C7%C5%AC%B2%BD%2F%A5%B5%A1%BC%A5%D0%A5%D1%A5%E9%A5%E1%A5%BF
他にも沢山解説サイトがあるので読む。
http://dev.mysql.com/doc/refman/4.1/ja/innodb-start.html
そして上記などの公式サイトの説明を読む。
$ mysqladmin variables
未設定時のデフォルト値がわからないので見る。
mysqlクラスターには関係ない。

2010-06-26

kvmのインストール

http://en.gentoo-wiki.com/wiki/KVM
http://www.linux-kvm.com/content/using-ksm-kernel-samepage-merging-kvm
http://foamy-capriccio.seesaa.net/article/109941507.html

まず無い場合はkernelに設定を追加します。
(例) それっぽい文字を探します。
$ find /lib/modules/*/ -type f -iname '*.o' -or -iname '*.ko' -ls|grep -i kvm

無い場合、設定を変えて再インストールします。
この例の場合genkernelを利用していますがmenuconfigの部分は同じです。
menuconfigは/で検索できます。
$ sudo genkernel --menuconfig all

[*] Virtualization  --->
<*>   Kernel-based Virtual Machine (KVM) support # ここは<M>でOK
<*>     KVM for AMD processors support           # ここは<M>でOK。CPU毎に異なる。無くても良い。

Device Drivers  --->
[*] Network device support  --->
<M>   Universal TUN/TAP device driver support

-*- Networking support  --->
Networking options  --->
<*> 802.1d Ethernet Bridging
<M> 802.1Q VLAN Support

# いらない?複数のゲストOSを動かす場合に有効な共有メモリ?
Processor type and features  --->
[*] Enable KSM for page merging

/dev/kvmが無いので、モジュールだとダメなのかと思い<*>に変えてインストールしましたがダメでした。
BIOSが原因でした。
$ dmesg | grep kvm
kvm: disabled by bios

マザーボードに依存する。
MA78GM-DS2HPの場合
起動時にDEL
Advanced BIOS Features
Virtualization [Disabled] => [Enabled]
Save & Exit Setup => Y

kernelの設定が成功の場合
$ ll /dev/kvm
crw-rw---- 1 root kvm 10, 232 2010-06-24 10:40:32 /dev/kvm

ここがMだと
<M>   Kernel-based Virtual Machine (KVM) support
<M>     KVM for AMD processors support
/etc/modules.autoload.d/kernel-2.6 などに
kvm-amdなどを書くと起動時に有効になります。
ディストリビューション毎に異なる場合が有ります。

手動
$ sudo modprobe kvm-amd

関連するパッケージをインストールします。
$ sudo vi /etc/portage/package.keywords
$ grep -i kvm /etc/portage/package.keywords
app-emulation/qemu-kvm
#$ sudo emerge -av app-emulation/qemu-kvm
$ sudo emerge -uav qemu-kvm usbutils bridge-utils usermode-utilities iptables
$ sudo gpasswd -a ユーザー名 kvm

インストールCDのイメージファイルをダウンロードします。
$ cd /mnt/share/kvm/
$ wget http://ftp.riken.jp/Linux/centos/5.5/isos/x86_64/CentOS-5.5-x86_64-bin-DVD-1of2.iso
$ qemu-img create -f qcow2 centos5.img 20G
$ kvm -hda centos5.img -cdrom CentOS-5.5-x86_64-bin-DVD-1of2.iso -boot d
$ sudo emerge -av net-misc/tigervnc

CentOS-5.5-x86_64-netinstall.iso にしたら途中で止まりました。
なのでDVDのisoファイルをダウンロードしました。
インストール項目のチェックを全部外す場合、CDの1枚目で大丈夫だったかもしれません。
http://ftp.riken.jp/Linux/centos/5.5/isos/x86_64/CentOS-5.5-x86_64-bin-1of8.iso など。

グラフィカルな環境で実行します。無い場合はqemu-kvm(kvm)コマンドでコンソールを指定して繋げると可能かもしれません。
$ vncviewer など (ssvncが接続設定を保存できたので楽かもしれません)
127.0.0.1:5900 を入力

なんだかんだで、centos5が起動したところ、ゲストOSから外にpingが通りませんでした。
OK ping 192.168.0.210 (centos5,ゲストOS)
OK ping 192.168.0.100 (gentoo,ホストOS)
NG ping 192.168.0.1   (ルーター)
NG ping www.example.com (外)

原因は /etc/sysctl.conf に余分な設定があるためでした。
sysctl.confをデフォルトの設定ファイルに戻して修正したところ成功しました。
反映させる場合、デフォルト値がわからない場合はsysctl -pより再起動した方が早いです。
-#net.ipv4.ip_forward = 0
+net.ipv4.ip_forward = 1

他の原因としてはiptablesが有効な場合ブリッジ(br0など)のFORWARDを通す設定が無いかもしれません。
# 追加する
$ sudo iptables -A FORWARD -i br0 -j ACCEPT
# 一旦止める
$ sudo /etc/init.d/iptables stop

セーブする場合、設定ファイルをバックアップすると良いです。
/var/lib/iptables/rules-save
/etc/sysconfig/iptables
など。

起動コマンドの例
$ sudo kvm -hda centos5.img -m 2048 -net nic,macaddr=52:54:00:12:34:56 -net tap,ifname=tap0,script=no,downscript=no &

ネットワークの設定(/etc/conf.d/net)の例
起動時に有効にする場合
bridge_br0="eth0 tap0"
brctl_br0=( "setfd 0" "sethello 10" "stp off" )
depend_br0 ()
{
  need net.eth0 net.tap0
}
config_br0=( "192.168.0.100/24" )
routes_br0=( "default via 192.168.0.1" )
dns_servers_br0="192.168.0.1"
config_tap0=( "null" )
tuntap_tap0="tap"
tunctl_tap0="-u root"
mac_tap0="52:54:00:12:34:56"
config_eth0=( "null" )

/etc/sysctl.conf のコメントアウトした設定の例
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_timestamps = 1

ホストOSの起動時に起動する。キーボードの種類を設定する例
$ /etc/conf.d
$ diff local.start.2010-07-03 local.start
8a9,10
>
> /usr/bin/kvm -k ja -hda /mnt/share/kvm/centos5/centos5.img -m 2048 -net nic,macaddr=52:54:00:12:34:57 -net tap,ifname=tap0,script=no,downscript=no &

2010-05-20

検索フォームの入力エリアとボタンを繋げるcssの例

bloggerで「このブログを検索」をサイバーに追加した場合の
検索フォームの入力エリアとボタンを繋げるcssの例です。
地味になります。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="ja" xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
 <head>
  <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
  <meta content="text/css" http-equiv="Content-Style-Type" />
  <meta content="text/javascript" http-equiv="Content-Script-Type" />
  <style type="text/css">
   <!--

body {
  background       :none repeat scroll 0 0 #F6F6F6;
  color            :#000000;
  font             :medium/1em monospace;
  margin           :1em 0 0 1em;
  padding          :0;
  word-wrap        :break-word;
}

#sidebar #CustomSearch1 {
  width            : 255px;
}

/* ================================================================ */
#sidebar table.gsc-search-box, #sidebar table.gsc-search-box * {
  font-family      :monospace;
  font-size        :medium;
  font-style       :normal;
  font-variant     :normal;
  font-weight      :normal;
  letter-spacing   :0;
  line-height      :1em;
  margin           :0;
  padding          :0;
  text-transform   :none;
  word-spacing     :0;
  word-wrap        :normal;
}

#sidebar table.gsc-search-box {
  border-collapse  :collapse;
  border-spacing   :0;
  border-style     :none;
  border-width     :0;
  margin-bottom    :2px;
  width            :100%;
}

#sidebar table.gsc-search-box td.gsc-input {
  background-color :#FFFFFF;
  border           :1px solid gray;
  margin           :0;
  padding          :0;
  width            :99%;
}

#sidebar input.gsc-input {
  background-color :#FFFFFF;
  border-width     :0;
  height           :1.5em;
  line-height      :1.5em;
  margin           :0;
  overflow         :hidden;
  padding          :0;
  vertical-align   :middle;
  width            :100%;
}

#sidebar table.gsc-search-box td.gsc-search-button {
  background-color :buttonface;
  border           :1px solid gray;
  margin           :0;
  padding          :0;
  vertical-align   :middle;
  width            :1%;
}

#sidebar input.gsc-search-button {
  background-color :buttonface;
  border-width     :0;
  cursor           :pointer;
  height           :1.5em;
  line-height      :1.5em;
  margin           :0;
  padding          :0;
  width            :3em;
}
/* ================================================================ */

     -->
  </style>
 </head>
 <body>
  <div id="sidebar">
   <div class="widget CustomSearch" id="CustomSearch1">
    <h2 class="title">このブログを検索</h2>
    <div class="widget-content">
     <div id="CustomSearch1_form">
      <form accept-charset="utf-8" class="gsc-search-box">
       <table cellspacing="0" cellpadding="0" class="gsc-search-box">
        <tbody>
         <tr>
          <td class="gsc-input"><input type="text" value="あいうえお" title="検索" name="search" class=" gsc-input" size="10" autocomplete="off" /></td>
          <td class="gsc-search-button"><input type="submit" title="検索" class="gsc-search-button" value="検索" /></td>
         </tr>
        </tbody>
       </table>
      </form>
     </div>
    </div>
   </div>
  </div>
 </body>
</html>

2010-05-15

formタグのmarginの単位をemにするとhtmlタグのfont-sizeを継承する例

IE6 or IE7 or IE8の互換モードで確認します。
formタグの中でmarginとfloatを同時に使う場合は、font-sizeがhtmlタグと同じ必要があるかもしれません。
例えば、formタグがfont-size:smallで、htmlタグがfont-size:mediumの場合、1emにつき3px多くmarginが発生するかもしれません。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!--<?xml version="1.0" encoding="UTF-8"?>-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
 <head>
  <title></title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <style type="text/css">
   <!--
* {
  margin: 0;
  padding: 0;
}

html {
  font-size: 100px;
}

body {
  font-size: 15px;
  padding: 1em;
}

p {
  font-size: medium;
  clear: both;
}

div, div button, form, form button {
  font-size: small;
}

div button, form button {
  border: 1px solid gray;
  float: left;
  margin-left: 1em;
  padding-left: 7em;
  width: 8em;
  height: 2em;
}

div button {
  background-color: #faa;
}

form button {
  background-color: #afa;
}
     -->
  </style>
 </head>
 <body>
  <p>div</p>
  <div>
   <button>1</button><button>2</button><button>3</button>
  </div>
  <p>form</p>
  <form>
   <button>1</button><button>2</button><button>3</button>
  </form>
 </body>
</html>

2010-04-26

javascript の IPアドレス の 計算


操作の説明
入力エリア

IPアドレス(ipv4, マスクを含む)を入力します。

submitボタン

出力エリアに結果を出力します。

resetボタン

入力エリア出力エリアを初期化します。

2回クリックすると入力エリアにサンプルの初期値が入ります。

sampleボタン

入力エリアにサンプルを入れます。

複数回クリックするとサンプルが切り替わります。

出力エリア

結果が出力されます。

出力エリアに複数の値を入力するにはresetボタンを押してからsampleボタンを押して改行で区切って入力してください。

入力した値はsubmitボタンを押すと出力結果で上書きされます。

一括入力のサンプルを表示するにはresetボタンを押してからsampleボタンを2回押してください。

出力エリアの説明
// Date:

開始時の日付です。

original:

入力内容です。

type:

入力内容のマスクのタイプです。

result(net):

結果です。

マスクはIPアドレスです。

result(bit):

結果です。

マスクは2進数の32桁目から右に連続する1の個数です。

連続する1が終わった後は0の連続が続きます。

表現できない場合はfalseを返します。

result(range):

結果です。

マスクは範囲(最後の値)を指定しています。

結果が期待した値にならない場合があります。

(例) 192.168.0.1-192.168.0.2
192.168.0.0-192.168.0.3 になります。
(2つのIPアドレスにはなりません)

また、グローバルなIPアドレスを付与されている場合のネットワークアドレス、ブロードキャストアドレスを表現している場合があります。

(例) 192.168.222.120/29
result(range) : 192.168.222.120-192.168.222.127
IPアドレスは8個で
ネットワークアドレスは     192.168.222.120
使えるIPアドレスは         192.168.222.121 ~ 192.168.222.126
ブロードキャストアドレスは 192.168.222.127

この場合classC:の内容に (network address) (broadcast address) が付くかどうかは無関係です。

num:

IPアドレスの数です。

IPアドレス/32 の場合に1として計算しています。

addr (bin):

mask (bin):とセットでresult(net):と同じ内容を2進数で表現しています。

mask (bin):

addr (bin):とセットでresult(net):と同じ内容を2進数で表現しています。

range(bin):

addr (bin):とセットでresult(range):と同じ内容を2進数で表現しています。

addr (hex):

mask (hex):とセットでresult(net):と同じ内容を16進数で表現しています。

mask (hex):

addr (hex):とセットでresult(net):と同じ内容を16進数で表現しています。

range(hex):

addr (hex):とセットでresult(range):と同じ内容を16進数で表現しています。

classA:

0.0.0.0-127.255.255.255にマッチした場合に表示されます。

10.0.0.0-10.255.255.255にマッチした場合 (private) を追加します。

9~32ビット目が0の場合 (network address) を追加します。

9~32ビット目が1の場合 (broadcast address) を追加します。

classB:

128.0.0.0-191.255.255.255にマッチした場合に表示されます。

172.16.0.0-172.31.255.255にマッチした場合 (private) を追加します。

17~32ビット目が0の場合 (network address) を追加します。

17~32ビット目が1の場合 (broadcast address) を追加します。

classC:

192.0.0.0-223.255.255.255にマッチした場合に表示されます。

192.168.0.0-192.168.255.255にマッチした場合 (private) を追加します。

25~32ビット目が0の場合 (network address) を追加します。

25~32ビット目が1の場合 (broadcast address) を追加します。

classD:

224.0.0.0-239.255.255.255にマッチした場合に表示されます。

IPv4 Multicast Address Space Registry

classE:

240.0.0.0-255.255.255.255にマッチした場合に表示されます。

localBroadcast:

255.255.255.255にマッチした場合に表示されます。

loopBack:

127.0.0.0/8にマッチした場合に表示されます。

--- separate ---

結果の区切り文字です。

// error

エラーです。

入力内容に数字が無い場合に表示されます。

2010-04-24

javascript の alert part2


操作の説明
1つ目のtextareaタグ
数値文字参照 文字実体参照 を入力して alertボタン または noalertボタン をクリックします。
2つ目のtextareaタグ と 1つ目のdivタグ に結果が出力されます。
2つ目のtextareaタグ
文字を入力して reverseボタン をクリックします。
1つ目のtextareaタグ に結果が出力されます。
1つ目のdivタグ
alertボタン または noalertボタン をクリックした際に結果が出力されます。
2つ目のdivタグ
ボタンをクリックした際に、ボタンの内容が出力されます。
3つ目のdivタグ
ボタンをクリックした際に、処理を終了した時刻が出力されます。
1つ目のbuttonタグ
alertボタン です。
クリックした際にポップアップを表示します。
2つ目のbuttonタグ
noalertボタン です。
ポップアップを表示しない以外は alertボタン と同じです。
3つ目のbuttonタグ
reverseボタン です。
4つ目のbuttonタグ
reverseボタン の設定を、逆送りに変更します。
5つ目のbuttonタグ
reverseボタン の現在の設定を表示します。
クリックした場合 reverseボタン の設定を、順送りに変更してから reverseボタン をクリックします。
6つ目のbuttonタグ
reverseボタン の設定を、順送りに変更します。
7つ目のbuttonタグ
resetボタン です。
1つ目のtextareaタグ と 2つ目のtextareaタグ と 1つ目のdivタグ と reverseボタン の設定を初期化します。
reverseボタン の設定の説明
default
可能な場合、文字実体参照を利用します。
数値文字参照の場合、10進数の数値文字参照の方が短い場合は、10進数の数値文字参照を利用します。
dec
10進数の数値文字参照を利用します。
hex
16進数の数値文字参照を利用します。
random
10進数の数値文字参照と、16進数の数値文字参照を、ランダムに利用します。
それぞれの数値文字参照の数値部分の手前に0~9文字のゼロを追加します。
50%の確率で数値文字参照のセミコロンを削除します。
def all
default の処理をする際に、半角スペースと改行を含めて処理します。
dec all
dec の処理をする際に、半角スペースと改行を含めて処理します。
hex all
hex の処理をする際に、半角スペースと改行を含めて処理します。
rand all
random の処理をする際に、半角スペースと改行を含めて処理します。

2010-04-23

javascript の alert


javascript の alert で html に記述されたエスケープされた文字を戻してから表示する例です。
セミコロンを省略すると各ブラウザで違った表示になる場合があります。
対応するフォントが無い場合は文字化けします。

http://www.w3.org/TR/REC-html40/sgml/entities.html
unhtmlspecialchars.min.2010-04-23.js.gz
<script type="text/javascript" src="unhtmlspecialchars.min.2010-04-23.js"></script>
<script type="text/javascript">
<!--
alert("&#12307; = " + unhtmlspecialchars("&#12307;"));
//-->
</script>

ブログ(blogspot.com)の機能で javascript の alert part2 と一緒に表示した時には動作しません。
javascript の alert part2

2010-04-22

javascript の String.fromCharCode

String.fromCharCode(0x2a6b2) が失敗します。

𪚲 (&#x2A6B2;)

理屈は 65536 以上(17ビット以上。0,1が17文字以上)の場合、
unicode番号の最大値から 65536 を引くと最大で 20ビット(1が20個。9999のような桁が上がる直前)になるので、
65536 以上の数値を 65536 引いて 10ビットずつの2つに分けて、
0~65535 の内、使われていない範囲を指定する6ビットを、分けた2つのそれぞれの頭につける。
(1文字目の 6ビット) (1文字目の 10ビット) (2文字目の 6ビット) (2文字目の 10ビット)
String.fromCharCode の場合、それを String.fromCharCode(1文字目の16ビット, 2文字目の16ビット) として渡すと1文字を表現できます。
1文字目の10ビット、2文字目の10ビットが変化するので
2^10 * 2^10 = 1,048,576
ということで100万種類ぐらいになると思います。

0 ~ 65535 までは16ビット
0xFFFF (bin)1111111111111111
0xFFFF (dec)65535
0xFFFF (bin, length)16
65536 以上は17ビット以上
0x10000 (bin)10000000000000000
0x10000 (dec)65536
0x10000 (bin, length)17
unicode の文字数
0x10FFFF (bin)100001111111111111111
0x10FFFF (dec)1114111
0x10FFFF (bin, length)21
65536 を引くと20ビット
0x10FFFF - 0x10000 (bin)11111111111111111111
0x10FFFF - 0x10000 (dec)1048575
0x10FFFF - 0x10000 (bin, length)20
num = 0x2A6B2 の場合
String.fromCharCode(0x2a6b2)文字化け
num (bin)101010011010110010
num (dec)173746
num (bin, length)18
# num (hex)2a6b2
num - 65536 した場合
num - 0x10000 (bin)11010011010110010
num - 0x10000 (dec)108210
num - 0x10000 (bin, length)17
# num - 0x10000 high,low1101001,1010110010
サロゲートペア1文字目に移動させる値
0xD800 (bin)1101100000000000
0xD800 (dec)55296
0xD800 (bin, length)16
# 0xD800 high,low110110,0000000000
# 110110 00 00000000d800
# 110110 01 00000000d900
# 110110 10 00000000da00
# 110110 11 00000000db00
# 110110 11 11111111dbff
サロゲートペア2文字目に移動させる値
0xDC00 (bin)1101110000000000
0xDC00 (dec)56320
0xDC00 (bin, length)16
# 0xDC00 high,low110111,0000000000
# 110111 00 00000000dc00
# 110111 01 00000000dd00
# 110111 10 00000000de00
# 110111 11 00000000df00
# 110111 11 11111111dfff
サロゲートペア1文字目
high ((num - 0x10000) >> 10)1101001
high mask1101100000000000
high result1101100001101001
high result (dec)55401
サロゲートペア2文字目
parseInt("1111111111", 2).toString(16)3ff
low ((num - 0x10000) & 0x3FF)1010110010
low mask1101110000000000
low result1101111010110010
low result (dec)57010
String.fromCharCode に2つ指定
String.fromCharCode(55401, 57010)𪚲

この文字設定をサロゲートペアといいます。
http://ja.wikipedia.org/wiki/Unicode%E4%B8%80%E8%A6%A7_D000-DFFF
http://ja.wikipedia.org/wiki/Unicode#.E3.82.B5.E3.83.AD.E3.82.B2.E3.83.BC.E3.83.88.E3.83.9A.E3.82.A2

2進数の 1xxxxxxxxxx >> 10 は 1になります。
// 例. 一桁目が消えて2桁目が1桁目になります。(2で割る。右シフト)
alert(parseInt("010", 2) >> 1); // 1 (01)
alert(parseInt("100", 2) >> 1); // 2 (10)
alert(parseInt("110", 2) >> 1); // 3 (11)
alert(parseInt("011", 2) >> 1); // 1 (01)
alert(parseInt("101", 2) >> 1); // 2 (10)
alert(parseInt("111", 2) >> 1); // 3 (11)

2進数の ??????????xxxxxxxxxx & 0x3FF(2進数で1が10個) は xxxxxxxxxx になります。
// 例. それぞれの桁で両方とも1の場合に、それぞれの桁が1になります。
alert(parseInt("010", 2) & parseInt("001", 2)); // 0 (000)
alert(parseInt("100", 2) & parseInt("001", 2)); // 0 (000)
alert(parseInt("110", 2) & parseInt("001", 2)); // 0 (000)
alert(parseInt("011", 2) & parseInt("001", 2)); // 1 (001)
alert(parseInt("101", 2) & parseInt("001", 2)); // 1 (001)
alert(parseInt("111", 2) & parseInt("001", 2)); // 1 (001)

high result, low result はオア演算です。
// 例. それぞれの桁でどちらかに1があれば、それぞれの桁を1にします。
alert(parseInt("010", 2) | parseInt("001", 2)); // 3 (011)
alert(parseInt("100", 2) | parseInt("001", 2)); // 5 (101)
alert(parseInt("110", 2) | parseInt("001", 2)); // 7 (111)
alert(parseInt("011", 2) | parseInt("001", 2)); // 3 (011)
alert(parseInt("101", 2) | parseInt("001", 2)); // 5 (101)
alert(parseInt("111", 2) | parseInt("001", 2)); // 7 (111)

ビット演算子は、他の言語でも同じように記述できる場合が多いです。
http://php.net/manual/ja/language.operators.bitwise.php

2進数、16進数は、理屈がわかっていれば暗算はできなくていいと思います。
buf = "";

buf += "### 0\n";
buf += parseInt("0",  2) + "\n"; // 0
buf += parseInt("0", 10) + "\n"; // 0
buf += parseInt("0", 16) + "\n"; // 0

buf += "### 1\n";
buf += parseInt("1",  2) + "\n"; // 1
buf += parseInt("1", 10) + "\n"; // 1
buf += parseInt("1", 16) + "\n"; // 1

//  2進数の10 = 0 1                             10
// 10進数の10 = 0 1 2 3 4 5 6 7 8 9             10
// 16進数の10 = 0 1 2 3 4 5 6 7 8 9 A B C D E F 10
buf += "### それぞれの 10\n";
buf += parseInt("10",  2) + "\n"; //  2 = ( 2 * 1)
buf += parseInt("10", 10) + "\n"; // 10 = (10 * 1)
buf += parseInt("10", 16) + "\n"; // 16 = (16 * 1)
buf += "### それぞれの 11\n";
buf += parseInt("11",  2) + "\n"; //  3 = ( 2 * 1) + 1
buf += parseInt("11", 10) + "\n"; // 11 = (10 * 1) + 1
buf += parseInt("11", 16) + "\n"; // 17 = (16 * 1) + 1

buf += "### 10進数と16進数の 99\n";
buf += parseInt(" 99", 10) + "\n"; //   99 =                 (10 * 9) + 9
buf += parseInt(" 99", 16) + "\n"; //  153 =                 (16 * 9) + 9
buf += "### 10進数と16進数の 999\n";
buf += parseInt("999", 10) + "\n"; //  999 = (10 * 10 * 9) + (10 * 9) + 9
buf += parseInt("999", 16) + "\n"; // 2457 = (16 * 16 * 9) + (16 * 9) + 9

buf += "### 16進数の F, FF\n";
buf += parseInt(" F", 16) + "\n";  //   15 =             15
buf += parseInt("FF", 16) + "\n";  //  255 = (16 * 15) + 15

buf += "### 2進数の 1111, 11111111\n";
buf += parseInt("    1111", 2) + "\n"; //   15 =                                 (2^3*1)+(2^2*1)+(2^1*1)+(2^0*1)
buf += parseInt("11111111", 2) + "\n"; //  255 = (2^7*1)+(2^6*1)+(2^5*1)+(2^4*1)+(2^3*1)+(2^2*1)+(2^1*1)+(2^0*1)

alert(buf);

他のやり方としては、割り算や、一旦文字列にする(非推薦)、などあります。
一旦文字列にして実行すると意味が理解しやすい場合があります。
ビット演算がやっていることが明確なのと早いそうなので良いです。
var nums, ret, i, num;
nums = new Array(0);
nums[0] = 0x2a6b2;
nums[1] = 0x296F0;
nums[2] = 12307;
nums[3] = -1;
nums[4] = 0;
nums[5] = 0x10FFFF;
nums[6] = 0x110000;
nums[7] = 65535;
nums[8] = 65536;
ret = "";
for (i = 0; i < nums.length; i++)
{
    if (nums[i] < 0)
    {
        ret = "Error";
    }
    else if (nums[i] <= 0xFFFF)
    {
        ret = "1: " + String.fromCharCode(nums[i]);
    }
    else if (nums[i] <= 0x10FFFF)
    {
        num = nums[i];
        num -= 0x10000;
        ret = "2: " + String.fromCharCode((num >> 10) | 0xD800, (num & 0x3FF) | 0xDC00);
    }
    else
    {
        ret = "Error";
    }
    alert("[" + i + "] " + nums[i] + " = " + ret);
}

0x110000 の場合 21桁目が1でその下が全部0の2進数になるので2文字とも 0xDC00 と同じになります。

正式名称は UTF-16BE でいいんだと思います。明確にするためにはBOM無しと記述すればいいのかもしれません。
http://ja.wikipedia.org/wiki/UTF-16

http://liosk.blog103.fc2.com/blog-entry-164.html?sess=83184307bdcf6494ab8d34a228efb8fe
http://en.wikipedia.org/wiki/UTF-16/UCS-2#Example_UTF-16_encoding_procedure
http://unicode.org/Public/UNIDATA/Blocks.txt

2010-04-20

javascript の new

javascript の new の例です。
保存して new1, new2 の順でクリックして下さい。
<html>
 <head>
 </head>
 <script type="text/javascript">
<!--

_str = "";
alert1 = function (str) {_str += str + "\n";};
alert2 = function () {alert(_str); _str="";};
new1q1 = "";
new1q2 = "";

function mynew(func)
{
    var ret = {}, key;
    if (typeof func == "function" &&
        func.prototype && typeof func.prototype == "object")
    {
        for (key in func.prototype)
        {
            ret[key] = func.prototype[key];
        }
        ret.__construct = func;
        ret.__construct();
        delete ret.__construct;
        ret.__test = "test";
    }
    return ret;
}

Base = {
    food: "毒キノコ",
    question: function()
    {
        return "あなたは" + this.food + "が好きですか?";
    },
    answer: function()
    {
        return "私は" + this.food + "が好きです。";
    }
};

function q1() {}

function q2()
{
    this.types = {
        like: "好き",
        hate: "嫌い",
        unknown: "わからない"
    };
    this.type = "unknown";
    this.answer = function()
    {
        return "私は" + this.food + "が" + this.types[this.type] + "です。";
    };
}

function new1()
{
    var obj1, obj2, key;

    alert1("q1 を new");
    q1.prototype = Base;
    obj1 = new q1();
    alert1(obj1.question());
    obj1.food = "ベニテングダケ";
    alert1(obj1.answer());
    alert1("typeof: " + typeof obj1);
    for (key in obj1)
    {
        alert1("key: " + key + ": " + typeof obj1[key]);
    }
    new1q1 = _str;
    alert2();

    alert1("q2 を new");
    q2.prototype = obj1;
    obj2 = new q2();
    obj2.type = "hate";
    alert1(obj2.question());
    obj2.food = "ニガクリタケ";
    alert1(obj2.answer());
    alert1("typeof: " + typeof obj2);
    for (key in obj2)
    {
        alert1("key: " + key + ": " + typeof obj2[key]);
    }
    new1q2 = _str;
    alert2();
}

function new2()
{
    var obj1, obj2, key;

    alert1(new1q1);
    alert1("q1 を mynew");
    q1.prototype = Base;
    obj1 = mynew(q1);
    alert1(obj1.question());
    obj1.food = "ベニテングダケ";
    alert1(obj1.answer());
    alert1("typeof: " + typeof obj1);
    for (key in obj1)
    {
        alert1("key: " + key + ": " + typeof obj1[key]);
    }
    alert2();

    alert1(new1q2);
    alert1("q2 を mynew");
    q2.prototype = obj1;
    obj2 = mynew(q2);
    obj2.type = "hate";
    alert1(obj2.question());
    obj2.food = "ニガクリタケ";
    alert1(obj2.answer());
    alert1("typeof: " + typeof obj2);
    for (key in obj2)
    {
        alert1("key: " + key + ": " + typeof obj2[key]);
    }
    alert2();
}

//-->
 </script>
 <body>
  <button onclick="javascript:new1();">new1</button>
  <button onclick="javascript:new2();">new2</button>
 </body>
</html>



for (key in obj) { ... } はオブジェクト用です。
for (i = 0; i < arr.length; i++) { ... } は配列用です。
obj = {0:"one", 1:"two"};
arr = Array("one", "two");
for (key in obj) {alert(obj[key]);}
for (i = 0; i < arr.length; i++) {alert(arr[i]);}

オブジェクトは 半角英字とアンダーバーとドル記号(2文字目から半角数字)だけの key の場合 obj.key と書けます。
__iterator__, __proto__ などがあるので __(アンダーバー2個)で始まる文字を使わないことをお勧めします。
また半角数字だけや、半角数字で始まる文字を使わないことをお勧めします。(obj.key と書けるため)
obj = {"0":"zero", "$":"one", "_":"two", "a":"a", "b001":"b001"};
//alert(obj.0);
alert(obj.$);
alert(obj._);
alert(obj.a);
alert(obj.b001);
alert(obj["0"]);
alert(obj["$"]);
alert(obj["_"]);
alert(obj["a"]);
alert(obj["b001"]);

obj1.food = "ベニテングダケ"; が obj2.food に引き継がれていますが、この動作が予想外であるという原因で不具合が発生するかもしれません。その場合 q2.prototype = Base; です。
function q2() の中で Base で定義される内容を拡張していますが、この動作が作法に則っているかどうかは不明です。
function mynew(func) の内容が new をある程度エミュレートしていますが、これは参考なので new を使ってください。
newを使う場合のお勧めはベースとなるオブジェクトを利用してnewしたオブジェクトは別のnewに使わないことです。ベースとなるオブジェクトが100回newされた結果の値だとしても、あなたの管轄ではなく、ソースを見ないですむほどのマニュアルがあれば問題ないです。よって問題が発生する場合があります。

http://www.glamenv-septzen.net/view/170

2010-04-19

jsparsenodetree.c part3

この記事は SpiderMonkey, jsparsenodetree, php の json_decode() を利用して jquery-1.4.2.min.js, prototype.js(1.6.1) の構造のjsonを php に読み込ませる際に修正した jsparsenodetree.c の差分の例です。

jsparsenodetree.c.2010-04-19.diff.gz

具体的には、特殊文字の一部のエスケープ、i++, ++i の向き、正規表現のオプション、関数の引数、関数内のローカル変数(関数)名、が修正対象です。

jsparsenodetree.c
jsparsenodetree.c part2

2010-04-18

javascript を短くしてみましょう 第5回

jquery-1.4.2.min.js を三度短くしてみましょう。

javascript を圧縮するツールはすでにあるので、そちらがお勧めです。
http://fnya.cocolog-nifty.com/blog/2007/08/yui_compressor__57c4.html
http://webos-goodies.jp/archives/51182388.html
http://dogmap.jp/2007/09/06/minify-javascript/
http://fnya.cocolog-nifty.com/blog/2009/10/microsoft-ajax-.html
http://aspnet.codeplex.com/releases/view/34488

jquery-1.4.2.min5.2010-04-18.js.gz (通常時: 約 70.2KB, 圧縮時: 約 22.7KB)

jquery-1.4.2.min.js と比べて 258 Byte 縮みました。
また簡単な動作テストしかしていないです。

今回の結論は、比較的に安全な動作変更を含むサイズ最適化の修正が、残されていることがわかりました。
例えば var x=parseFloat; とすると 167 Byte 前後縮むかもしれません。

「javascript を短くしてみましょう」としての結論は、ライブラリの場合、公式サイトで配布されているjsファイルをそのまま使うのが1番良い、ということです。圧縮する場合は javascript のコーディングと圧縮ツールの選定者が同一か、関連する他者すべての同意を得て、実績のあるツールを利用する、といった処理が必要な場合があります。
また、javascriptの文法を理解する勉強にはなります。書いてある内容の意味(どうしてそう書いてあるのか)の勉強には(少ししか)なりません。

今回の javascript を短くする方法は、前回に利用した方法を利用しています。
×の部分は反映されていませんので不可能であるかもしれません。
○ ライセンスを除くコメントの削除。
○ ローカルな変数、関数名の変更。
○ スペース(文法的なワーニングを含む、動作の変更を含まない)の削除。
○ セミコロン(文法的なワーニングを含む、動作の変更を含まない)の削除。
× グローバルな変数、関数名を沢山利用されている場合にローカル変数に代入して置き換える。
× var a; var b; を var a, b; にする。(連続するvar宣言をまとめる) 追記: function(){for(var i=0;i<xxx;i++){}var j=0;for(var k in xxx){}} → function(){var i,j,k; ...}
× if(xxx){yyy} を if(xxx)yyy; にする。({...}の中の処理が単独な場合{}を消す)
× function xxx(){...}; のセミコロンを消す。(処理が無いセミコロンを消す)
× 到達することが無いifブロックなどを消すということをする機能がツールによってはあるそうです。

また jquery を使う場合 click, getWH, k, i という名前はグローバルな変数、関数名に使わない方がいいかもしれません。
click, k
d.attachEvent("onclick",function k(){ ... d.detachEvent("onclick",k)});

getWH, i
function i(){e=b=== ... ==0?i():c.swap(a,ob,i);
追記: 変数(関数名)のスコープの判定が間違っていました。下記の場合にxxx()がグローバルな関数ではないことが明確であることを判断できていないです。
function () { ... if (...) { ... function xxx(){ ... } ... xxx() ... } ... }
function () { ... if (...) { ... function xxx(){ ... xxx() ... } ... } ... }

「javascript を短くしてみましょう」で利用したツールは下記になります。
javascript パーサ
SpiderMonkey jsparsenodetree 他には ECMAScript パーサ で探すと良いのがあるかもしれません。
全体的な処理
php コマンド (5.2.13-pl0-gentoo) パース結果のツリー構造のデータの処理や、検証のための別のアプローチの処理(例:pcreの正規表現)で利用します。 好きな言語であれば何でも良いはずです。
圧縮
gzip コマンド (1.4) phpのgzip関数より結果が良いため利用しています。

「javascript を短くしてみましょう」のツールのphp部分の作成の流れは下記になります。
(1)
javascriptの完全に把握している1KB~5KBの短いファイルを用意します。
(2)
(1)のツリー構造のデータを元に、コメントやスペースを削除するだけの処理を作成します。
(3)
1文字ずつ読むか、正規表現か、得意な方で(2)と同じ処理を作成します。ツリー構造のデータを扱うのに慣れている場合で、かつ、ECMAScript系に詳しい場合は任意です。
(4)
(2),(3)が同じ内容になるまで、修正します。動くことを確認します。
(5)
変数を短くしたりする機能を(2)に追加します。その際(3)と同じ出力をできる機能を残します。(3)自体に機能を追加するのは大変なので諦めます。
(6)
(1)のファイルを別のファイルにして(2)~(5)を繰り返します。 別ファイルの候補は、ある程度長く、いろいろな書き方で記述されているファイルを2つ以上です。
(7)
一通りできたところでjavascriptを出力する直前のデータがあると思うので、変数名を入れ替える処理を追加して圧縮率を上げます。 ...A... より ...B... の方が圧縮した際に短くなる場合がある、という処理の連続です。この処理は任意です。例えばjqueryの場合1.5~2時間かかります。gzipのアルゴリズムの知識のある場合、もっと早く、小さくできるのかもしれません。

追記: ...(3)自体に機能を追加するのは大変なので諦めます。...の部分の例です。
// (a), (b), (c), (d) は b と名乗る関数の場所
// (1), (2), (3), (4) は外側の b ではない b を定義した場合

str = "";
function b(){str = "" + str + 1;}                         //     (a)
function a(c) {
    b();                                                  //     (b)
    //if (c==1){var b = function (){str = "" + str + 2;}} // (1) (c)
    //if (c==1){function b(){str = "" + str + 3;}}        // (2) (c)
    //{function b(){str = "" + str + 4;}}                 // (3) (c)
    //function b(){str = "" + str + 5;}                   // (4) (c)
    b();                                                  //     (d)
}
a(1);
a(2);
alert(str);

// 無し: 1111                 (a,b,c,d) 全て同じ名前で(a)に合わせる。
// (1) : b is not a function
// (2) : 1311                 (a,b,c,d) 全て同じ名前で(a)に合わせる。
// (3) : 1414                 (a,b) (c,d) がそれぞれ同じ名前
// (4) : 5555                 (b,c,d) が同じ名前で (a)は無関係
結局のところ、ツリー構造か、似たデータを作成するようになるかもしれないので、であれば、最初からツリー構造のデータが欲しいと思うかもしれません。
jquery-1.4.2.min5.2010-04-18.js.gz の場合(4)以外の例ではbをすべてグローバル変数として扱っています。よって、変数名の縮小の対象外になっています。しかし該当する部分が k,i と元から短いです。
よって function b(){} を function の中の function 以外の {...} の中に書く場合は function a(c) { var b; ... } とすると、変数(関数)のスコープが明確です。

javascript を短くしてみましょう 第1回
javascript を短くしてみましょう 第2回
javascript を短くしてみましょう 第3回
javascript を短くしてみましょう 第4回