2011年3月8日火曜日

Fedora 14 に Go 言語をインストール

ふと目にとまってしまった Go 言語を、少し試してみようと、まずは、Fedora 14 x86_64 へインストールしてみました。
手順(各所に情報があるようですが)とログをメモしておきます。

まず、root で必要なものをインストールします。特に、Mercurial を。
[root@fedora14 ~]# cat /etc/redhat-release 
Fedora release 14 (Laughlin)
[root@fedora14 ~]# uname -a
Linux fedora14 2.6.35.10-74.fc14.x86_64 #1 SMP Thu Dec 23 16:04:50 UTC 2010 x86_64 x86_64 x86_64 GNU/Linux

[root@fedora14 ~]# yum install '*mercurial*'
途中省略

[root@fedora14 ~]# rpm -q bison gcc libc6-dev ed gawk make  ※必要なものを確認
bison-2.4.3-1.fc14.x86_64
gcc-4.5.1-4.fc14.x86_64
package libc6-dev is not installed  ※これは、既に名前が変わったのか、不要でした
ed-1.4-2.fc14.x86_64
gawk-3.1.8-3.fc14.x86_64
make-3.82-3.fc14.x86_64
次に一般ユーザでの作業です。
[user00@fedora14 ~]$ cat .bashrc  ※環境変数を設定します
# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# User specific aliases and functions

export GOROOT=$HOME/go  ※この4行をvi等で追加
export GOOS=linux
export GOARCH=amd64
export GOBIN=$HOME/bin

[user00@fedora14 ~]$ source .bashrc
[user00@fedora14 ~]$ mkdir $GOROOT
[user00@fedora14 ~]$ mkdir $GOBIN

※次の Mercurial のコマンド hg で、リポジトリからソースその他一式をゲット
[user00@fedora14 ~]$ hg clone -r release https://go.googlecode.com/hg/ $GOROOT
warning: go.googlecode.com certificate with fingerprint b1:af:83:76:f3:81:b0:57:70:d8:07:42:c8:c1:b3:67:38:c8:7a:bc not verified (check hostfingerprints or web.cacerts config setting)
adding changesets
adding manifests
adding file changes
added 7570 changesets with 29247 changes to 4124 files
updating to branch default
2508 files updated, 0 files merged, 0 files removed, 0 files unresolved

※ビルドを実行
[user00@fedora14 ~]$ cd $GOROOT/src
[user00@fedora14 src]$ ./all.bash 
rm -f *.o y.tab.[ch] y.output a.out lib9.a
rm -f *.o y.tab.[ch] y.output a.out libbio.a
rm -f *.o y.tab.[ch] y.output a.out libmach.a
rm -f *.o y.tab.[ch] y.output a.out cc.a
途中省略

--- cd ../test
1 known bugs; 0 unexpected bugs  ※ちょっと気になりますが…後述の helloworld.go は動きました。

ALL TESTS PASSED

---
Installed Go for linux/amd64 in /home/user00/go.
Installed commands in /home/user00/bin.
The compiler is 6g.
[user00@fedora14 src]$ 
お試しに helloworld.go です。
package main

import "fmt"

func main() {
        fmt.Printf("hello, world\n")
        return
}
これを、6g および 6l にかけると、6.out という実行モジュールが生成されます。
[user00@fedora14 ~]$ 6g helloworld.go    ※コンパイル
[user00@fedora14 ~]$ ls -l helloworld.6
-rw-rw-r-- 1 user00 user00 5750 Mar  8 22:52 helloworld.6
[user00@fedora14 ~]$ 6l helloworld.6     ※リンク
[user00@fedora14 ~]$ ls -l 6.out 
-rwxrwxr-x 1 user00 user00 1842238 Mar  8 22:53 6.out
[user00@fedora14 ~]$ ./6.out    ※実行
hello, world
コマンド先頭が数字というのは、結構、違和感があります。bash の history もうまく動かないです。!6g などとやると、history の 6番目 のコマンドが呼び出されてしまいます。

2011年3月6日日曜日

Fedora 14 でコマンドを打ち間違えると・・・

Fedora 14 でコマンドを打ち間違えると、何やらネットアクセスを行って、どこかにその(打ち間違えた)コマンドがないかを探しにいく。これって、アイデアとしてはありなのでしょうけど、わたしは邪魔に感じます。(デフォルトでその動きは、どうなのかな。好みの問題もありますが。)

挙動からそういう動きがあるとは思いつつ放ってましたが、ふとどこでその処理をやっているか考えてみたら、そうか bash が何かやっているに違いないと思い。set を打ったところ、次のような関数が設定されていることに気がつきました。
[root@fedora14 ~]# set
...
command_not_found_handle () 
{ 
    runcnf=1;
    retval=127;
    [ ! -S /var/run/dbus/system_bus_socket ] && runcnf=0;
    [ ! -x /usr/libexec/packagekitd ] && runcnf=0;
    if [ $runcnf -eq 1 ]; then
        /usr/libexec/pk-command-not-found $@;
        retval=$?;
    else
        echo "bash: $1: command not found";
    fi;
    return $retval
}
この関数を unset command_not_found_handle すれば、ネットアクセスを停止できます。.bashrc にでも書いておけばよい。いったいどこでこの設定が行われているか探ってみると、次の場所でした。
[root@fedora14 ~]# grep -r command_not_found_handle /etc
/etc/profile.d/PackageKit.sh:command_not_found_handle () {
なお、未インストールのコマンドを打った場合、次のように便利に機能することもあります。
[root@fedora14 ~]# resize
bash: resize: command not found...
Install package 'xterm' to provide command 'resize'? [N/y] 
 * Running.. 
 * Resolving dependencies.. 
 * Downloading update information.. 
 * Waiting for authentication.. 
 * Waiting in queue.. 
 * Resolving dependencies.. 
 * Downloading packages.. 
 * Testing changes.. 
 * Installing packages.. 
 * Scanning applications.. 
COLUMNS=80;                                                                    
LINES=34;
export COLUMNS LINES;

2011-03-07追記
bash のオンラインマニュアルに次のような記述があります。
COMMAND EXECUTION
       After a command has been split into words, if it results in a simple command and
       an optional list of arguments, the following actions are taken.

       If the command name contains no slashes, the shell attempts to  locate  it.   If
       there  exists  a  shell  function  by  that  name,  that  function is invoked as
       described above in FUNCTIONS.  If the name does not match a function, the  shell
       searches  for  it  in  the  list  of  shell builtins.  If a match is found, that
       builtin is invoked.

       If the name is neither a shell function nor a builtin, and contains no  slashes,
       bash  searches each element of the PATH for a directory containing an executable
       file by that name.  Bash uses a hash table to remember  the  full  pathnames  of
       executable  files  (see hash under SHELL BUILTIN COMMANDS below).  A full search
       of the directories in PATH is performed only if the command is not found in  the
       hash  table.   If  the  search is unsuccessful, the shell searches for a defined
       shell function named command_not_found_handle.  If that function exists,  it  is
       invoked  with  the  original command and the original command's arguments as its
       arguments, and the function's exit status becomes the exit status of the  shell.
       If  that  function is not defined, the shell prints an error message and returns
       an exit status of 127.

2011年3月5日土曜日

gawkで配列の要素数を得る方法

gawk で配列の要素数を得る場合 len=0 ; for (e in a) len++ のように書いていました。
しかし、perl なら @a か $#a+1 、bash なら ${#a[@]} 、Ruby なら a.size または a.length などと書けるし、もしかして gawk でも簡単に記述できるのでは?と思って、man を見たところ、gawk-3.1.5 以降であれば、length(a) と書けることを知りました。
ただ、わたしの場合、仕事上、古いバージョンもサポートする必要があり、使えないのですが、ここにメモしておきます。

まずは、man gawk(1) から抜粋です。
       length([s])             Returns the length of the string s, or the length of  $0
                               if s is not supplied.  Starting with version 3.1.5, as a
                               non-standard extension, with an array argument, length()
                               returns the number of elements in the array.
次に、テストスクリプトです。
#!/bin/gawk -f
#
# test_length_array.gawk
#
# memo:
#   length(array) returns the number of elements with gawk-3.1.5 or later
#   see man gawk(1)
#
function my_len(a,      len) {
        len=0
        for (i in a) len++
        return len
}
function chk_support_length_for_array() {
        return system("gawk 'BEGIN {a[1]=1;length(a);exit(0)}' >/dev/null 2>&1")
}
BEGIN {
        for (i=100; i<777+100; i++) {
                a[i]=i
        }
        if (PROCINFO["version"] == "") {
                f="gawk --version" ; f | getline ; ver=$3 ; close(f)
                printf "INFO: gawk-%s does not supports PROCINFO[\"version\"]\n", ver
        } else {
                ver=PROCINFO["version"]
                printf "INFO: gawk-%s supports PROCINFO[\"version\"]\n", ver
        }
        if (chk_support_length_for_array()) {
                printf "WARNING: gawk-%s does not supports length(array)\n", ver
        }
        printf "my_len(a)=%d\n", my_len(a)
        printf "length(a)=%d\n", length(a)
        exit(0)
}
配列に対する length をサポートするか確認する関数も書いてみました。あと、これも知らなかったのですが、gawk-3.1.4 以降であれば、PROCINFO["version"] という組み込み変数を使えるようです。これを、Fedora 14 で実行してみると、次のようになります。
[root@fedora14 ~]# ./test_length_array.gawk 
INFO: gawk-3.1.8 supports PROCINFO["version"]
my_len(a)=777
length(a)=777
古いシステムだと、次のようにエラーになります。
# ./test_length_array.gawk 
INFO: gawk-3.0.6 does not supports PROCINFO["version"]
WARNING: gawk-3.0.6 does not supports length(array)
my_len(a)=777
gawk: ./test_length_array.gawk:33: fatal: attempt to use array `a' in a scalar context
人気ブログランキングへ にほんブログ村 IT技術ブログへ