2012-03-28

RHEL6: runit: /usr/bin/ld: cannot find -lc

RHEL6 で runit-2.1.1 を make するとエラーが発生。

./compile runit.c
./load runit unix.a byte.a -static
/usr/bin/ld: cannot find -lc
collect2: ld returned 1 exit status
make[1]: *** [runit] Error 1
make[1]: Leaving directory `/package/admin/runit-2.1.1/compile'

さてどうしたもんかと思ったら、先人は偉かった。

その patch。

--- src/Makefile.orig	2009-10-05 05:44:02.000000000 +0900
+++ src/Makefile	2011-12-28 17:21:46.956241394 +0900
@@ -6,10 +6,10 @@
 	./check-local $(IT)
 
 runit: load runit.o unix.a byte.a
-	./load runit unix.a byte.a -static
+	./load runit unix.a byte.a
 
 runit-init: load runit-init.o unix.a byte.a
-	./load runit-init unix.a byte.a -static
+	./load runit-init unix.a byte.a
 
 runsv: load runsv.o unix.a byte.a time.a
 	./load runsv unix.a byte.a time.a

2012-03-14

Bash: builtin command `local' returns status

成功したら何も出さないけど、失敗したらエラー内容を出力して終わりたい、ということがある。

test1.sh:

#!/bin/bash

compute() {
    $((3 / 0))
}

echo -n 'computing ... '
out=$(compute 2>&1)
ret=$?
if [ $ret -eq 0 ] ; then
    echo '[OK]'
else
    echo '[NG]'
    echo "$out"
fi
exit $ret

これは意図通りに動く。

$ bash test1.sh
computing ... [NG]
test1.sh: line 4: 3 / 0: division by 0 (error token is "0")

しかし Bash を使っていて local を使わないなんて あり得ない ので、

test2.sh:

#!/bin/bash

compute() {
    $((3 / 0))
}

main() {
    echo -n 'computing ... '
    local out=$(compute 2>&1)
    local ret=$?
    if [ $ret -eq 0 ] ; then
	echo '[OK]'
    else
	echo '[NG]'
	echo "$out"
    fi
    return $ret
}

main
$ bash test2.sh
computing ... [OK]

はい、動かなくなったー。何で!?

長い間この理由が分からなくて、挙句 Bash のバグじゃねーの?と疑ったこともあったが、ずっと後になって謎が解けた。

local が実行結果を返すなんて知らなかったよ・・・。 orz

local は関数内で使われる限り失敗しないので、「local out=$(...)」の結果は常に真になる。なので正しくはこう。

test3.sh:

#!/bin/bash

compute() {
    $((3 / 0))
}

main() {
    echo -n 'computing ... '
    local out
    out=$(compute 2>&1)
    local ret=$?
    if [ $ret -eq 0 ] ; then
	echo '[OK]'
    else
	echo '[NG]'
	echo "$out"
    fi
    return $ret
}

main
$ bash test3.sh
computing ... [NG]
test3.sh: line 4: 3 / 0: division by 0 (error token is "0")

もう Bash さん、疑ったりして本当にすみません。