Wednesday, November 8, 2017, 22:48 - OS, OS / Linux
Posted by ELIN
xinetdやincrondでスペースを含む引数を指定すると意図したように動かない
スペースに限らずワンライナを仕込んだり、パイプで繋いだり、リダイレクトでゲロしたり、複数のコマンドを実行させたいときには、まず意図した挙動にならないだろう
一方でcrondはこれを回避して動いてくる

例えば以下のようなperlのワンライナをxinetdで設定する
server = /usr/bin/perl
server_args = -lnpe '...' >/var/log/hoge.log

コード部は省略するが、これの意図するところはログを吐き出したいのだ

ところがこれは往々にしてperlのsyntax errorで止まる

原因はlinuxを使っている人なら簡単に予想できるが、要するにcrondはシェルの上で走らせている(/etc/crontabのSHELLで指定しているのを知っているだろう)のでパイプやリダイレクトを使えるというわけ

ところがxinetdやincrondは何も考えずスペースで区切って渡してしまう

以下のような小文字へコンバートしてエコーするだけのサービスを考える
server = /usr/bin/perl
server_args = -lnpe '$_ = lc($_)'

これはうまく動かない
何も考えず、perlでいうところの"split(/ /,...)"で分解して渡してしまうので、perlのバイナリに渡される引数は...
$ARGV[0] # -lnpe
$ARGV[1] # '$_
$ARGV[2] # =
$ARGV[3] # lc($_)'

こんなんなってしまう、こんな区切り方じゃ動かせる感じがしない

これと同様の悩みは調べればすぐに見付かって、解決方法も至極簡単に書いてある
.shファイルを書いて(例題の場合はそのまま.plに起こせば良いね)そいつをxinetdやincrondから呼び出せばいい

しかしながらたった1行のコマンドやリダイレクトのためだけにファイルに起こすのはちょっと馬鹿馬鹿しい気もするのだ

linuxはwindowsのようなカスみたいなシェルじゃないのでもっと頭のいい(ひねくれた)方法があるだろうと考えた結果、こちら
server = /bin/sh
server_args = -c $* - eval perl -MPOSIX=strftime -lnpe 's/\r//;$.==1&&print$ENV{REMOTE_HOST}." - - [".strftime("%d/%b/%Y:%T %z",gmtime($^T))."] \"$_\"";!length()&&print&&exit;s/^/\t/' >>/var/log/honeypot.log && echo HTTP/1.0 200 OK;echo

パイプやリダイレクトの動作から/bin/shの実行は必須として、evalに被せることで後ろの文字列を実行させる
1行のhttp honeypotの完成だ、めでたしめでたし
1 comment ( 506 views )
Saturday, March 2, 2013, 12:51 - OS / Linux
Posted by ELIN
先日t5720がヤフオクで12台セット10800円だったので知り合いと共同購入

内6台が届いた
(\10800+送料\5160)/12で\1330/台、お得

早速展開、まあ中身の画像はGoogleですぐ出てくるが

問題はこの角度

PCIだが「超ロープロなカードなら刺さるんじゃね」とか「ライザーカード使うんじゃね」とか話してたが、実物を見るとメモリほどの余裕しかないし、ライザーカードでなんとかする隙間すらなかった
別に使う予定はないからいいけど、仮に使うなら側板を外して運用か、穴を空けるしかない

さてDebianで運用する方法だが、flashが512MBしかないのでいくらDebianでも通常の方法では容量不足でインストールできない
最も単純な解決方法は諦めてDSLなどを使用することだが、Debianの豊富なリポジトリを使いたいのでだめ
多少古くてもいいならt5725のfirmwareを使うという手もある
但しflash向けに最適化されておらず、I/Oが直接flashへ入るので寿命が気になってくるのでだめ

色々と考えたが最終的にはrorootでaufsが噛んでいれば一応は最低要件を満たせるので、live-helperを使うことにした
幸いlive-helperがusbflash向けのddイメージを作成できるようなので、まあusbではないがddでぶちこんでしまえば起動くらいはするだろうという考え

早速作成とその検証にかかるが、この仮定であることに気付く
live-helperで作成するイメージはいわゆるスナップショット機能を含んでいる
今のlivecdなら大体この機能を持っていて、これはlivecdで起動して作業データをusbflashへ自動で保存してくれるというやつで、要するにlivecdとusbflashを持ち歩けばどこでも作業環境が呼び出せるというやつだ

この機能をうまく使えばインテリスイッチなどで見る設定変更後保存しない限り再起動すると元の状態で立ち上がってくるというような本当のfirmwareっぽい実装ってできるよね?と
だが探してみるとlive-helper自体ドキュメント不足な感じがあるし、そもそもこういうハック的な情報が出てこないので1つ1つ検証することになった

まずスナップショット機能としては4種類から選べる
・live-rw
・home-rw
・live-sn
・home-sn
でlive-*はファイルシステム全体(/以下)を対象とし、home-*は(恐らく、未検証)/home以下を対象とする
これはデバイスを跨がない、単純に言えばrsync -xと同様の動作だが、例えば/tmpがtmpfsでマウントされている場合、/tmp以下は対象とならない
また/etc/live-snapshot.exclude_listに記述されているものも対象にならない
*-rwは起動時に-o rwで該当するデバイスをマウントし、以降そのデバイスへI/Oを流す
つまり基本的に即反映される、何らかの変更はその後に電源を引っこ抜いてもファイルシステムが正常であるとするなら反映されている
*-snは起動時に前回保存された差分をramfsへ展開し、以降のI/Oもそのramfsへ反映される
このramfsのデータは正常終了時に新たな差分として該当デバイスへ書き出し、haltする
つまり電源を引っこ抜かれると途中の変更は全て消失することになる

この4種類の名称は識別子で、例えばHDDを繋いでそのHDDが/dev/sdbならば
mke2fs -L live-rw /dev/sdb1
tune2fs -L live-rw /dev/sdb1

などで識別子をボリュームラベルに設定すると起動時に認識し、そのようなデバイスとして扱う
この場合であればファイルシステムへの変更は/dev/sdb1へ即座に保存され、次回以降も特殊な操作を必要とせず、前回と同様の状態で起動する

但しこれらは完全に自動で認識してくれるわけではなく、kernelパラメータとして"persistent"を渡す必要がある
persistentを渡さない場合、どういう状態であれ無視されてデフォルトの状態で起動する
また基本的には直下(と表現すべきか……)しか探してくれないので例えばlive-snで差分データが/live/live-sn.cpio.gzのような場所(rootfsからの話ではないことに注意、詳細は後述)に保存されている場合はpersistentを渡した上で"persistent-path=/live/"(末尾/必須?)も渡す必要が出てくる
persistent-pathは通常渡す必要がないが、live-snapshotコマンドで融通を利かせたい場合に使うことになる

live-snapshotコマンドは任意のタイミング、任意の場所を任意の場所へスナップショットを保存でき、この機能の自由度を高めてくれる
使い方は単純で
live-snapshot -r /:/dev/sdb1:/live/live-sn.cpio.gz
のようにスナップショットを保存元、保存先デバイス、そのパスを":"で区切って-rで渡す
例のlive-sn.cpio.gzのlive-snの部分は識別子で、その影響を受ける
なのでこの名称は必ず4種類のいずれかでなければ読み込んでくれない

さて、話を戻して要件をまとめると
・flash saveでファイルシステムのスナップショットを保存、但し一部除く(/var/logなど)
・flash clearでスナップショットを破棄、ファクトリーデフォルトに戻る
・上記2点以外の操作でスナップショットは変更されない
と、なる

まずこのflashコマンドは
#!/bin/sh

case $1 in
save)
live-snapshot -r /:`df /live/image|awk '/^\/dev\//{print$1}'`:/live/live-sn.cpio.gz
;;
clear)
mount -o remount,rw `df /live/image|awk '/^\/dev\//{print$1}'`
rm -f /live/image/live/live-sn.cpio.gz
mount -o remount,ro `df /live/image|awk '/^\/dev\//{print$1}'`
;;
*)
;;
esac

こんなスクリプトを/sbinに置き
lb config --bootappend-live "persistent persistent-path=/live/"
と、する
スナップショットはrootfsから見ると/live/image/live/以下にlive-sn.cpio.gzとして保存され、起動時に読み込まれるようになる
flashである/dev/sda1は/live/imageにマウントされていて、その/live以下にrootfs(filesystem.squashfs)があるので、同一のディレクトリにイメージを保存したいという理由でこうしている

しかしこれは想定の動作をしない
何故ならlive-sn.cpio.gzを読み込んだ時点でこれがスナップショットの保存先であることをinitrdの中で/etc/live/boot.d/snapshot.confに出力している
これがOSの正常終了時に/etc/init.d/live-bootに読み込まれ、自動的にlive-snapshotを実行してしまうために任意ではないタイミングでスナップショットが保存されてしまう
本来はそうあるべきだろうが、今回の要件ではロールバックさせなければならないのでこの制御を削除する必要がある

方法は様々あるが、最も簡単なのは/etc/live/boot.d/snapshot.confを読ませないことで、これは
#!/bin/sh
sed -i 's/^.*\. \${SNAPSHOT_CONF}$/#&/' /etc/init.d/live-boot

なファイルをlive-helperのconfig/chroot_local-hooks/以下に置いておけば解決する

これでflashに優しいfirmware的な何かが作れるようになった

実際に使っているスクリプトはこちら

これでOS部分は完成したので次はcomサーバに取りかかる
comサーバとは何なのか、ということだがこのt5720にusb-rc232変換を挿しまくってシリアルが必須な機器をt5720へのssh経由で管理できるようにしようというもの

これはぶろぐの内容的にはオマケみたいなもので
まず
ttyS0:x:1000:20::/home/com:/bin/sh
ttyS1:x:1000:20::/home/com:/bin/sh
ttyS2:x:1000:20::/home/com:/bin/sh
ttyS3:x:1000:20::/home/com:/bin/sh
ttyUSB0:x:1000:20::/home/com:/bin/sh
ttyUSB1:x:1000:20::/home/com:/bin/sh
ttyUSB2:x:1000:20::/home/com:/bin/sh
ttyUSB3:x:1000:20::/home/com:/bin/sh

こういう感じにユーザを作る

で、/home/com/.profileを
#!/bin/sh

if [ -c /dev/$LOGNAME ];then
case $LOGNAME in
ttyS0)
bps=115200
;;
ttyUSB0)
bps=9600
;;
*)
;;
esac

screen -xRR -S $LOGNAME /dev/$LOGNAME $bps
fi

と、する

こうすることでt5720へttyUSB0でsshを張ると即座にシリアルポートが使えるようになるというわけです
add comment ( 5802 views )
Wednesday, February 20, 2013, 01:39 - OS / Linux
Posted by ELIN
要件は
・小さくする
・NILFS2を使えるようにする
・起動直後にrsync daemonが動くようにする

live-helperを使った1cd-Linuxの作成方法自体は日本語圏でもぐぐればそれなりに出てくるが、パッケージの追加方法は書かれていても除外方法が書かれていない(英語圏でも見当たらない、言う程調べてないが)
幸いlb(lh_config/lh_buildだのlhだの書いてあるが、今はlb)やその実体の中身は単なるシェルスクリプトで、実体は/usr/share/live/build/scripts/build/以下にある
順番に読んでいくとconfig/bootstrapのLB_BOOTSTRAP_EXCLUDEがそれだとわかり、最終的にdebootstrapの--excludeとして与えられる

試しに
debootstrap --print-debs squeeze .
で出力されるパッケージを全て突っ込んでみたが、最低必要とされるパッケージは無視されるようで、例えばbase-filesは確実に入る
またaptは除外できるが必須のようで、aptを含めない場合lb buildで失敗する
実際にやってみて余り変化はないようだが、aptを除く全て書いておくと若干小さくなる

逆にパッケージの追加は簡単で、config/chroot_local-packageslists/以下に.listなるファイルを作成し、必要なパッケージを記述すればいい
もしくはlb configの--packagesで与える
例えばNILFS2がほしいので
lb config --packages=nilfs2-tools
とする

起動直後にrsync daemonを動かすには
・/etc/rsyncd.confを作る
・/etc/default/rsyncのRSYNC_ENABLEを書き換える
上記2つの手順が必要になる

前者はconfig/chroot_local-includes/etc/以下にrsyncd.confを配置すれば自動的に含めてくれる
つまりconfig/chroot_local-includes/が1cdの/に対応している

後者も同じ方法でいけそうな気がするが、config/chroot_local-hooks/以下にスクリプトを書いておくとiso作成時に走らせることができるので、それで書き換えることにした
例えば
#!/bin/sh

sed -i 's/^\(RSYNC_ENABLE\)=.*/\1=true/' /etc/default/rsync

をconfig/chroot_local-hooks/rsyncd.shとしてchmod +xする
ちなみにこのスクリプトはchrootされてから走る

これでめでたく完成

実際に動かしたのはこちら

参考
http://yakushi.shinshu-u.ac.jp/robotics/?DebianLive%2FBuild-HOWTO-for-the-Impatient
http://www.sakopc.info/hiki/hiki.cgi?Devian+Live
add comment ( 13699 views )

| 1 |