約 1,494,722 件
https://w.atwiki.jp/aerocats/pages/62.html
/sbinとは /sbinの構成 実際に標準Linuxの/sbinがどのようになっているのかを見てみる。 コマンド 備考 説明 adjtimex BusyBoxのシンボリックリンク depmod dhcpcd e2fsck fsck.ext2のシンボリックリンク fdisk BusyBoxのシンボリックリンク freeramdisk BusyBoxのシンボリックリンク fsck BusyBoxのシンボリックリンク fsck.ext2 fsck.ext3 fsck.ext2のシンボリックリンク fsck.minix BusyBoxのシンボリックリンク getty BusyBoxのシンボリックリンク halt BusyBoxのシンボリックリンク hdparm BusyBoxのシンボリックリンク hwclock BusyBoxのシンボリックリンク ifconfig BusyBoxのシンボリックリンク ifdown BusyBoxのシンボリックリンク ifup BusyBoxのシンボリックリンク init BusyBoxのシンボリックリンク insmod BusyBoxのシンボリックリンク klogd BusyBoxのシンボリックリンク ldconfig loadkmap BusyBoxのシンボリックリンク logread BusyBoxのシンボリックリンク losetup BusyBoxのシンボリックリンク lsmod BusyBoxのシンボリックリンク makedevs BusyBoxのシンボリックリンク mdev BusyBoxのシンボリックリンク mke2fs mkfs.ext2のシンボリックリンク mkfs.ext2 mkfs.ext3 mkfs.ext2のシンボリックリンク mkfs.minix BusyBoxのシンボリックリンク mkswap BusyBoxのシンボリックリンク modinfo modprobe BusyBoxのシンボリックリンク nameif BusyBoxのシンボリックリンク pivot_root BusyBoxのシンボリックリンク poweroff BusyBoxのシンボリックリンク reboot BusyBoxのシンボリックリンク rmmod BusyBoxのシンボリックリンク route BusyBoxのシンボリックリンク runlevel BusyBoxのシンボリックリンク setconsole BusyBoxのシンボリックリンク shutdown start-stop-daemon BusyBoxのシンボリックリンク sulogin BusyBoxのシンボリックリンク swapoff BusyBoxのシンボリックリンク swapon BusyBoxのシンボリックリンク switch_root BusyBoxのシンボリックリンク sysctl BusyBoxのシンボリックリンク syslogd BusyBoxのシンボリックリンク tune2fs vconfig BusyBoxのシンボリックリンク watchdog BusyBoxのシンボリックリンク zcip BusyBoxのシンボリックリンク
https://w.atwiki.jp/aerocats/pages/49.html
標準Linuxの/etc/init.d/内にある。 スクリプト スクリプト詳細configure関数 set_defaultGw関数 set_defaultIp関数 set_defaultIf関数 set_dns関数 start関数 stop関数 スクリプト本体 スクリプト #!/bin/sh # # start/stop network deamons # # DHCPCD=/sbin/dhcpcd BASE=`basename $DHCPCD` LOCK=/var/lock/networking . /usr/local/bin/kuro_lib if [ -f /etc/netinfo ]; then . /etc/netinfo fi # for dhcpcd.exe export INTERFACE=$ENETNAME configure() { echo "create network files.." echo "IP=[$my_ipaddress], netmask=[$my_subnetmask], dgw=[$my_dgw], dns1=[$my_dns1], dns2=[$my_dns2]" if [ "$my_ipaddress" = "" ]; then my_ipaddress=$DEFAULT_IP my_subnetmask=255.255.255.0 my_dgw= fi touch /etc/resolv.conf } set_defaultGw() { if [ "$my_dgw" = "" ]; then route del default else route add default gw $my_dgw fi } set_defaultIp() { echo "** setting default ip" /sbin/ifconfig $ENETNAME $DEFAULT_IP netmask 255.255.255.0 # delete default gw my_dgw= } set_defaultIf() { TMP=`cat /proc/net/route |awk {print $4} |grep 0003` if [ "$TMP" = "" ]; then echo "add default if" #route add -net 255.255.255.255 netmask 255.255.255.255 $ENETNAME route add -net default $ENETNAME fi } set_dns() { echo "Configuration resolv.conf" cat /dev/null /etc/resolv.conf if [ "$my_dns1" != "" ]; then echo "nameserver $my_dns1" /etc/resolv.conf fi if [ "$my_dns2" != "" ]; then echo "nameserver $my_dns2" /etc/resolv.conf fi } start() { configure /sbin/ifconfig lo up killall $BASE rm -f /etc/dhcpc/dhcpcd-eth0.pid # delete default gw while do /sbin/route del default if [ $? -ne 0 ]; then break fi done sleep 1 echo "Configuration network interface lo $ENETNAME" ## ## change mtu (frame-size 1518,4100,7418) ## if [ "$mtu" = "4102" ] ; then mtu=4084 elif [ "$mtu" = "7422" ] ; then mtu=7404 elif [ "$mtu" = "9694" ] ; then mtu=9676 else mtu=1500 fi /sbin/ifconfig $ENETNAME mtu $mtu multicast if [ $? -ne 0 ]; then echo "mtu fail" /sbin/ifconfig $ENETNAME mtu 1500 multicast fi if [ "$my_ipaddress" = "dhcp" ]; then if [ "$my_dgw" != "" ]; then echo "--- set static dgw" DHCP_GW="-G $my_dgw" fi ## see also /etc/dhcpc/dhcpcd.exe echo "DHCPCSTATE=requesting" /var/tmp/dhcpcstate ## echo "requesting DHCP tout=30[s]" $DHCPCD -L /etc/dhcpc -h `hostname` $DHCP_GW -t 15 $ENETNAME if [ $? -ne 0 ]; then echo "** dhcp fail" echo "DHCPCSTATE=fixip" /var/tmp/dhcpcstate set_defaultIp set_defaultGw # wait linkup delay sleep 4 fi else echo "DHCPCSTATE=fixip" /var/tmp/dhcpcstate echo "/sbin/ifconfig $ENETNAME $my_ipaddress netmask $my_subnetmask" /sbin/ifconfig $ENETNAME $my_ipaddress netmask $my_subnetmask if [ $? -ne 0 ]; then set_defaultIp fi set_defaultGw set_dns fi ## set_defaultIf ## set ipaddress in /etc/hosts /etc/init.d/sethostname.sh #/usr/local/bin/change_notify.sh network } stop() { echo "Deconfiguration network interface lo $ENETNAME" killall $BASE /sbin/ifconfig $ENETNAME down /sbin/ifconfig lo down } # for NFS TMP=`grep /dev/root /proc/mounts|grep nfs` if [ "$TMP" != "" ]; then echo "nfs root mode. skip $ENETNAME network configuration." exit 0 fi # lock_file check lock_file create case "$1" in start) start ;; stop) stop ;; restart) stop sleep 1 start ;; *) echo "Usage $0 {start|stop|restart}" ;; esac lock_file delete exit 0 スクリプト詳細 ブロックごとに見てみる。 #!/bin/sh # # start/stop network deamons # # シェルにshを指定。ネットワークデーモンの開始/停止のコメント。 DHCPCD=/sbin/dhcpcd BASE=`basename $DHCPCD` LOCK=/var/lock/networking DHCPCDという変数を用意し、そこに/sbin/dhcpcdを代入。 BASEという変数を用意し、そこに basename /sbin/dhcpcd を代入。 LOCKという変数を用意し、そこに/var/lock/networkingを代入。 . /usr/local/bin/kuro_lib /usr/local/bin/kuro_libをサブシェルで走らせる。 kuro_lib内の DEFAULT_IP変数(=192.168.11.150) ENETNAME変数(=eth0) lock_file関数 を使用するためだ。 if [ -f /etc/netinfo ]; then /etc/netinfoが存在すれば(/etcにnetinfoというファイルがあれば)以下を実行。 . /etc/netinfo /etc/netinfoをサブシェルで走らせる。 netinfo内の my_ipaddress変数 my_subnetmask変数 my_dgw変数 my_dns1変数 my_dns2変数 mtu変数 を使用するためだ。 fi /etc/netinfoの存在の有無の条件分岐を終了。 # for dhcpcd.exe /etc/dhcpc/dhcpcd.exeのために、というコメント。 export INTERFACE=$ENETNAME 環境変数を設定するexportコマンドで、INTERFACE変数にeth0を代入している。 ここからは7つの関数の記述になる。 configure関数 configure() { configure関数の定義が始まる。 echo "create network files.." echo "IP=[$my_ipaddress], netmask=[$my_subnetmask], dgw=[$my_dgw], dns1=[$my_dns1], dns2=[$my_dns2]" 画面に create network files.. IP=[IPアドレス値], netmask=[ネットマスク値], dgw=[デフォルトゲートウェイ値], dns1=[DNS1値], dns2=[DNS2値] と表示される。 if [ "$my_ipaddress" = "" ]; then my_ipaddress変数に何も設定されていなければ以下を実行。 my_ipaddress=$DEFAULT_IP my_subnetmask=255.255.255.0 my_dgw= my_ipaddress変数にDEFAULT_IP変数の値、my_subnetmask変数に255.255.255.0、my_dgw変数は空、とそれぞれの変数に値を代入。 fi my_ipaddress変数が空かどうかの条件分岐を終了。 touch /etc/resolv.conf /etcにresolv.confというファイルを作成。 } configure関数はここまで。 set_defaultGw関数 set_defaultGw() { set_defaultGw関数の定義ここから。 if [ "$my_dgw" = "" ]; then my_dgw変数が空であれば以下を実行。 route del default routeコマンド?でデフォルト経路情報を削除。 デフォルト経路とは、自分の経路情報に記録されていない宛て先のパケットを送るためのものだ。 一般的にはルーターを指す。 else my_dgw変数が空でなければ以下を実行。 route add default gw $my_dgw routeコマンド?で、デフォルト経路としてmy_dgw変数の内容を経路テーブルに追加。 fi my_dgw変数が空かどうかの条件分岐を終了。 } set_defaultGw関数はここまで。 set_defaultIp関数 set_defaultIp() { set_defaultIp関数はここから。 echo "** setting default ip" /sbin/ifconfig $ENETNAME $DEFAULT_IP netmask 255.255.255.0 画面上に「** setting default ip」と表示。 ifconfigコマンド?でeth0にDEFAULT_IP変数の値とnetmaskを255.255.255.0を設定。 # delete default gw my_dgw= デフォルトゲートウェイを削除する、というコメントの後にmy_dgw変数に空を代入している。 } set_defaultIp関数はここまで。 set_defaultIf関数 set_defaultIf() { set_defaultIf関数はここから。 TMP=`cat /proc/net/route |awk {print $4} |grep 0003` TMPという変数を用意して、そこに「cat /proc/net/route |awk {print $4} |grep 0003」の結果を代入している。 3つの命令をパイプでつないでいるのだが、ひとつづつ見てみる。 cat /proc/net/route /proc/net/routeを読み込んで次の命令に渡す。 この/procにはprocファイルシステムがマウントされていて、カーネルの各種統計情報を閲覧することができるが、/proc/net/routeにはIP経路情報が記載されている。 このコマンドを実行してみると Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT eth0 0001A8C0 00000000 0001 0 0 0 00FFFFFF 0 0 0 eth0 00000000 0101A8C0 0003 0 0 0 00000000 0 0 0 というように出力された。 awk {print $4} awkコマンド?で第4パラメータを抜き取って次の命令へ。 第4パラメータとは、上の表から「Flags」のことだとわかる。 grep 0003 「0003」という文字列を検索している。 実際に「0003」という文字列があったので、この場合、TMP変数には「0003」と入る。 フラグ「0003」とは「経路は有効でゲートウェイを使用する」という内容だ。 今の例で言うなら、宛て先が「0.0.0.0/0」なので選ばれた経路はデフォルト経路である。 つまり、この一連の命令は「デフォルト経路をeth0が持っているかどうか」を調べていたのだ。 なければ空白が入る。 if [ "$TMP" = "" ]; then TMP変数が空なら以下を実行。 echo "add default if" 画面に「add default if」と表示。 #route add -net 255.255.255.255 netmask 255.255.255.255 $ENETNAME route add -net default $ENETNAME routeコマンド?でeth0経由のネットワーク255.255.255.255を追加する、はコメントアウトされ、routeコマンド?でeth0にデフォルト経路を追加している。 コメントアウトされている255.255.255.255/32の経路情報は「ローカルブロードキャスト」と呼ばれるもので、ルーターを超えないLAN内に一斉にパケットを送信する手段である。 fi TMP変数の内容の条件分岐を終了する。 } set_defaultIf関数はここまで。 set_dns関数 set_dns() { set_dns関数はここから。 echo "Configuration resolv.conf" 画面に「Configuration resolv.conf」と表示する。 cat /dev/null /etc/resolv.conf /etc/resolv.confの内容を消去している。 if [ "$my_dns1" != "" ]; then my_dns1変数が空でなければ以下を実行。 echo "nameserver $my_dns1" /etc/resolv.conf 「nameserver my_dns1変数の値」を/etc/resolv.confに追記。 fi my_dns1変数が空かどうかの条件分岐を抜ける。 if [ "$my_dns2" != "" ]; then my_dns2変数が空でなければ以下を実行。 echo "nameserver $my_dns2" /etc/resolv.conf 「nameserver my_dns2変数の値」を/etc/resolv.confに追記。 fi my_dns2変数が空かどうかの条件分岐を終了する。 } set_dns関数はここまで。 start関数 start() { start関数の定義が始まる。 configure configure関数の実行。 /sbin/ifconfig lo up ifconfigコマンド?でlo(ループバック)デバイスを始動する。 killall $BASE killallコマンド?で「basename /sbin/dhcpcd」を停止する、という内容だが、basenameコマンド?で/sbin/dhcpcdを「dhcpcd」と削ってkillallコマンド?に渡している。 結果的には「killall dhcpcd」となる。 rm -f /etc/dhcpc/dhcpcd-eth0.pid /etc/dhcpc/dhcpcd-eth0.pidをrmコマンド?で消去する。 # delete default gw デフォルトゲートウェイを削除する、とのコメント。 while do /sbin/route del default if [ $? -ne 0 ]; then break fi done while文による無限ループだ。 /sbin/route del default routeコマンド?でデフォルト経路を削除し if [ $? -ne 0 ]; then break fi routeコマンド?がエラーの終了ステータス「1」を返すまでbreak文でループから抜けられない。 sleep 1 1秒数えたあと echo "Configuration network interface lo $ENETNAME" 画面上に「Configuration network interface lo eth0」と表示。 ## ## change mtu (frame-size 1518,4100,7418) ## mtuの変更、とのコメント。 if [ "$mtu" = "4102" ] ; then mtu=4084 elif [ "$mtu" = "7422" ] ; then mtu=7404 elif [ "$mtu" = "9694" ] ; then mtu=9676 else mtu=1500 fi mtu変数が 4102であればmtu変数に4084を代入 7422であればmtu変数に7404を代入 9694であればmtu変数に9676を代入 それ以外ならmtu変数に1500を代入 という内容だ。 /sbin/ifconfig $ENETNAME mtu $mtu multicast ifconfigコマンド?でeth0のmtuを上で判別した値に設定しマルチキャストフラグを立てる。 if [ $? -ne 0 ]; then echo "mtu fail" /sbin/ifconfig $ENETNAME mtu 1500 multicast fi ifconfigコマンド?がエラーの場合、画面上に「mtu fail」と表示し、eth0のmtuを1500に設定しマルチキャストフラグを立てる。 if [ "$my_ipaddress" = "dhcp" ]; then my_ipaddress変数が「dhcp」であれば以下を実行。 if [ "$my_dgw" != "" ]; then my_dgw変数が空でなければ以下を実行。 echo "--- set static dgw" DHCP_GW="-G $my_dgw" 画面上に「--- set static dgw」と表示。 DHCP_GWという変数を用意し、「-G $my_dgw」を代入。 fi my_dgw変数が空かどうかの条件分岐を終了する。 ## see also /etc/dhcpc/dhcpcd.exe echo "DHCPCSTATE=requesting" /var/tmp/dhcpcstate /etc/dhcpc/dhcpcd.exeを参照、とのコメント。 /var/tmp/dhcpcstateに「DHCPCSTATE=requesting」を書き込み。 ## echo "requesting DHCP tout=30[s]" 画面上に「requesting DHCP tout=30[s]」と表示する。 $DHCPCD -L /etc/dhcpc -h `hostname` $DHCP_GW -t 15 $ENETNAME /sbin/dhcpcd -L /etc/dhcpc -h `hostname` $DHCP_GW -t 15 eth0 を実行。 if [ $? -ne 0 ]; then エラーが返れば以下を実行。 echo "** dhcp fail" 画面上に「** dhcp fail」と表示する。 echo "DHCPCSTATE=fixip" /var/tmp/dhcpcstate /var/tmp/dhcpcstateに「DHCPCSTATE=fixip」と書き込む。 set_defaultIp set_defaultGw set_defaultIp関数とset_defaultGw関数を実行する。 # wait linkup delay sleep 4 リンクが始動するのを4秒間待つ。 fi dhcpcdコマンドがエラーを返すかどうかの条件分岐を終了する。 else my_ipaddress変数が「dhcp」でなければ以下を実行。 echo "DHCPCSTATE=fixip" /var/tmp/dhcpcstate /var/tmp/dhcpcstateに「DHCPCSTATE=fixip」と書き込む。 echo "/sbin/ifconfig $ENETNAME $my_ipaddress netmask $my_subnetmask" /sbin/ifconfig $ENETNAME $my_ipaddress netmask $my_subnetmask /sbin/ifconfig eth0 $my_ipaddress netmask $my_subnetmask を実行。 if [ $? -ne 0 ]; then エラーが返れば以下。 set_defaultIp set_defaultIp関数を実行。 fi エラーかどうかの判別終了。 set_defaultGw set_dns set_defaultGw関数、set_dns関数の実行。 fi my_ipaddress変数が「dhcp」かどうかの条件分岐を終了する。 ## set_defaultIf set_defaultIf関数を実行する。 ## set ipaddress in /etc/hosts /etc/init.d/sethostname.sh /etc/hostsにIPアドレスを設定する、というコメント。 /etc/init.d/sethostname.shの実行。 #/usr/local/bin/change_notify.sh network /usr/local/bin/change_notify.sh networkの実行はコメントアウトだ。 } start関数はここまで。 stop関数 stop() { stop関数はここから。 echo "Deconfiguration network interface lo $ENETNAME" 画面上に「Deconfiguration network interface lo eth0」と表示する。 killall $BASE killallコマンド?で「basename /sbin/dhcpcd」を停止する、という内容だが、basenameコマンド?で/sbin/dhcpcdを「dhcpcd」と削ってkillallコマンド?に渡している。 結果的には「killall dhcpcd」となる。 /sbin/ifconfig $ENETNAME down ifconfigコマンド?でeth0を停止している。 /sbin/ifconfig lo down ifconfigコマンド?でlo(ループバック)デバイスを停止している。 } stop関数はここまで。 スクリプト本体 # for NFS NFS用の分岐。NFSとは「Network File System」の略。 ネットワーク上のデバイスを自分のファイルのように扱えるファイルシステムだ。 TMP=`grep /dev/root /proc/mounts|grep nfs` TMPという変数を用意し、そこに「grep /dev/root /proc/mounts|grep nfs」を代入している。 1つめのgrep /proc/mountsから/dev/rootという文字列を検索している。その結果を次に渡す。 2つめのgrep 渡された結果からnfsという文字列を検索している。 これらはつまり「/dev/rootがnfs形式でマウントされているかどうか」を調査しているということだ。 この結果は「(空)」か「nfs」というどちらか2つしかない。 if [ "$TMP" != "" ]; then TMP変数が空でなければ以下を実行。 つまり/dev/rootがnfs形式でマウントされていれば、という条件だ。 echo "nfs root mode. skip $ENETNAME network configuration." 画面上に「nfs root mode. skip eth0 network configuration.」と表示。 exit 0 終了ステータスに正常を示す「0」を設定しスクリプトを終了する。 fi TMP変数が空かどうかの条件分岐を終了。 lock_file check /usr/local/bin/kuro_libのlock_file関数にcheckという引数を付けて実行。 lock_file関数を見てみる。 lock_file関数 lock_file(){ lock_file関数はここから。 case $1 in 第1引数の内容で処理内容を分岐する。 checkの場合 check) [ -f "${LOCK}" ] echo "${THIS_SCRIPT} already runnign" /var/lock/networkingが存在すれば、画面上に「${THIS_SCRIPT} already runnign」と表示する。 ちなみに行末の「runnign」は「running」のスペルミスだろう。 return 1 ;; 戻り値に「1」を設定しlock_file関数を終了する。 createの場合 create) echo "${THIS_SCRIPT}" $2 ${LOCK} ;; 「${THIS_SCRIPT} 第2引数」と/var/lock/networkingに書き込む。 deleteの場合 delete) rm -f ${LOCK} ;; /var/lock/networkingを消去する。 delete_logの場合 delete_log) rm -f ${LOCK}.log ;; /var/lock/networking.logを消去する。 それ以外の場合 *) ;; 何もしない。 esac 第1引数の内容による処理振り分けを終了する。 } lock_file関数はここまで。 lock_file create case "$1" in start) start ;; stop) stop ;; restart) stop sleep 1 start ;; *) echo "Usage $0 {start|stop|restart}" ;; esac lock_file delete exit 0
https://w.atwiki.jp/aerocats/pages/44.html
Debian Projectという団体が作成するLinuxディストリビューション。 同団体が作成するOSは他にもDebian GNU/Hurd、Debian GNU/NetBSD、Debian GNU/kFreeBSDなどがあるため、単にDebianとしただけでは本来正しくはないが、一般的にはDebian=Linuxディストリビューションと言えるだろう。 「保守的」「厳格」といったイメージが持たれることもしばしばだが、フリーソフトウェアの健全な発展を目指すことを理念として掲げる団体としても有名だ。 Debian GNU/Linuxの特長 aptコマンドでの強力なパッケージ管理は初心者にでもすんなり受け入れられるだろう。 書籍やネット上での扱いはRedhat系よりは少ないため、情報量としてはFedoraシリーズには劣るかもしれない。 提供しているパッケージの数はLinuxディストリビューションの中でもっとも多く、アプリケーションの導入で困ることは少ないと言える。 Debianに付けられるコードネーム Debianを知るにつれて「etch」「sarge」といった単語を目にする。 これはDebianのバージョンごとに付けられた名前で、映画「トイ・ストーリー」のキャラクター名があてられている。 バージョン コードネーム キャラクター 1.1 buzz バズ。元は主人公「ウッディー」のライバル 1.2 rex レックス。気弱な恐竜おもちゃ 1.3 bo ボー。ウッディーが憧れるランプ人形 2.0 hamm ハム。ブタの貯金箱 2.1 slink スリンキー。ダックスフントのバネのおもちゃ 2.2 potato ミスターポテト。じゃがいも型のおもちゃ 3.0 woody ウッディー。主人公のカウボーイ 3.1 sarge サージェント。アーミーの小さな人形 4.0 etch エッチ・ア・スケッチ。おもちゃのお絵かきボード lenny レニー。双眼鏡 sid シド。隣に住む子ども
https://w.atwiki.jp/aerocats/pages/52.html
標準Linuxの/usr/local/sbin/内にある。 開発用Linuxに必要な材料をHDDに展開する役割を担う。 また、ユーザーの意思次第でHDDブートの設定も行う。 動作内容 スクリプト スクリプト詳細HDDブートの準備 U-Boot環境変数の設定 動作内容 /mnt/mtdにhddrootfs.tar.gz、uImage.buffaloがあるかどうかを確認して以下を実行。 ある場合 /mnt/bootディレクトリを作成し、/dev/sda1をext3形式でマウントして、そこにuImage.buffaloをコピーする。 /mnt/rootfsディレクトリを作成し、/dev/sda2をxfs形式でマウントして、そこにhddrootfs.tar.gzを展開する。 デバイス マウントポイント マウント形式 /dev/sda1 /mnt/boot ext3 /dev/sda2 /mnt/rootfs xfs /usr/local/bin/kuro_libを/mnt/rootfs/usr/local/binにコピーする。 ChangeMyUbootEnvがあればU-Boot環境変数を書き換える。なければそのまま終了する。 ない場合 エラー終了させる。 スクリプト #!/bin/sh . /usr/local/bin/kuro_lib TMP_BOOT_MPT=/mnt/boot TMP_ROOT_MPT=/mnt/rootfs HDD_ROOTFS=${MTD_MPT}/hddrootfs.tar.gz UIMAGE=${MTD_MPT}/uImage.buffalo CHANGE_UBOOT_ENV=${MTD_MPT}/ChangeMyUbootEnv # check material if [ -e ${HDD_ROOTFS} -a -e ${UIMAGE} ] ; then # I believe sda is already fdisked and format is finished. # That s a KUROBOX quality....www # mkdir ${TMP_BOOT_MPT} mkdir ${TMP_ROOT_MPT} mount -t ext3 ${DISK1_DEV}1 ${TMP_BOOT_MPT} [ $? -ne 0 ] exit 1 mount -t xfs ${DISK1_DEV}2 ${TMP_ROOT_MPT} [ $? -ne 0 ] exit 1 cp -afp ${UIMAGE} ${TMP_BOOT_MPT}/ tar -zxvf ${HDD_ROOTFS} -C ${TMP_ROOT_MPT}/ cp -f /usr/local/bin/kuro_lib ${TMP_ROOT_MPT}/usr/local/bin/ # OK! prepare of hdd is finished. # change u-boot environment or not ? if [ -e ${CHANGE_UBOOT_ENV} ] ; then nvram -c set default_kernel_addr 0x00100000 nvram -c set bootargs_base console=ttyS0,115200 nvram -c set bootargs_root root=/dev/sda2 rw panic=5 nvram -c set bootargs console=ttyS0,115200 root=/dev/sda2 rw panic=5 BOOTVER=1.09 nvram -c set bootcmd ide reset; ext2load ide 0 1 $(default_kernel_addr) /$(kernel); bootm $(default_kernel_addr) nvram -c set nand_boot no fi # OK! u-boot environment is changed. else exit 1 fi スクリプト詳細 ブロックごとに見てみる。 #!/bin/sh . /usr/local/bin/kuro_lib シェルにshを指定して、/usr/local/bin/kuro_libをサブシェルで実行している。 このkuro_lib内の MTD_MPT変数(=/mnt/mtd) DISK1_DEV変数(=/dev/sda) を使用するためだ。 TMP_BOOT_MPT=/mnt/boot TMP_ROOT_MPT=/mnt/rootfs HDD_ROOTFS=${MTD_MPT}/hddrootfs.tar.gz UIMAGE=${MTD_MPT}/uImage.buffalo CHANGE_UBOOT_ENV=${MTD_MPT}/ChangeMyUbootEnv TMP_BOOT_MPTという変数を用意し、そこに/mnt/bootを代入。 TMP_ROOT_MPTという変数を用意し、そこに/mnt/rootfsを代入。 HDD_ROOTFSという変数を用意し、そこに/mnt/mtd/hddrootfs.tar.gzを代入。 UIMAGEという変数を用意し、そこに/mnt/mtd/uImage.buffaloを代入。 CHANGE_UBOOT_ENVという変数を用意し、そこに/mnt/mtd/ChangeMyUbootEnvを代入。 # check material 必要材料のチェック。 HDDブートの準備 if [ -e ${HDD_ROOTFS} -a -e ${UIMAGE} ] ; then /mnt/mtd/hddrootfs.tar.gzが存在し、かつ/mnt/mtd/uImage.buffaloも存在するならば次を実行する。 # I believe sda is already fdisked and format is finished. # That s a KUROBOX quality....www # 「sdaはもうfdiskされフォーマットもされていると信じています。これが玄箱クオリティです。」とコメントされている。 mkdir ${TMP_BOOT_MPT} mkdir ${TMP_ROOT_MPT} mkdirコマンド?で/mnt/bootと/mnt/rootfsというディレクトリを作成している。 mount -t ext3 ${DISK1_DEV}1 ${TMP_BOOT_MPT} mountコマンドで、/dev/sda1をext3形式で/mnt/bootにマウントしている。 [ $? -ne 0 ] exit 1 そのmountコマンド実行時に終了ステータスが「0」(つまり正常)でなければ、終了ステータス「1」(つまり異常)を設定しスクリプトを終了する。 mount -t xfs ${DISK1_DEV}2 ${TMP_ROOT_MPT} mountコマンドで、/dev/sda2をxfs形式で/mnt/rootfsにマウントしている。 [ $? -ne 0 ] exit 1 そのmountコマンド実行時に終了ステータスが「0」(つまり正常)でなければ、終了ステータス「1」(つまり異常)を設定しスクリプトを終了する。 cp -afp ${UIMAGE} ${TMP_BOOT_MPT}/ cpコマンド?で/mnt/mtd/uImage.buffaloを/mnt/boot/にコピーしている。 「-afp」オプションは、「-a」で「できるだけ属性や構造を保持する」、「-f」で「同名ファイルを警告せずに上書きする」、「-p」で「パーミッションやタイムスタンプを保持したままコピー」という意味だ。 tar -zxvf ${HDD_ROOTFS} -C ${TMP_ROOT_MPT}/ tarコマンドで/mnt/mtd/hddrootfs.tar.gzを/mnt/rootfs/に展開している。 「-zxvf」オプションは、「-z」で「アーカイブ展開と同時にzip形式での解凍も行う(拡張子:.tar.gz)」、「-x」で「アーカイブからファイル・ディレクトリを取り出す」、「-v」で「処理の詳細を表示する」、「-f」で「アーカイブファイルのファイル名/デバイスファイル名を指定する」という意味だ。 cp -f /usr/local/bin/kuro_lib ${TMP_ROOT_MPT}/usr/local/bin/ ふたたびcpコマンド?で/usr/local/bin/kuro_libを/mnt/rootfs/usr/local/bin/に「-f」オプション(同名ファイルを警告せずに上書きする)でコピーしている。 # OK! prepare of hdd is finished. HDDの準備は完了しました、とのコメント。 # change u-boot environment or not ? U-Bootの環境も変更するかどうか、というコメント。ここからU-Bootの環境変数の変更処理だ。 U-Boot環境変数の設定 if [ -e ${CHANGE_UBOOT_ENV} ] ; then /mnt/mtd/ChangeMyUbootEnvが存在すれば次を実行。 nvram -c set default_kernel_addr 0x00100000 nvram -c set bootargs_base console=ttyS0,115200 nvram -c set bootargs_root root=/dev/sda2 rw panic=5 nvram -c set bootargs console=ttyS0,115200 root=/dev/sda2 rw panic=5 BOOTVER=1.09 nvram -c set bootcmd ide reset; ext2load ide 0 1 $(default_kernel_addr) /$(kernel); bootm $(default_kernel_addr) nvram -c set nand_boot no nvramコマンド?を使ってU-Boot環境変数を設定している。 各環境変数の変更内容については環境変数について?で説明する。 ここではルートファイルシステムを/dev/sda2、ブートするカーネルを/dev/sda1、NANDフラッシュからのブートはしない、という設定になっている。 fi /mnt/mtd/ChangeMyUbootEnvの有無の条件分岐を終了する。 # OK! u-boot environment is changed. U-Boot環境を変更しました、というコメント。 実際は/mnt/mtd/ChangeMyUbootEnvがなくてもここを通るので「変更しました」では間違っているが、コメントなので問題はない。 else /mnt/mtd/hddrootfs.tar.gzかあるいは/mnt/mtd/uImage.buffaloがなければ以下を実行。 exit 1 終了ステータスに「1」(つまり異常)を設定しスクリプトを終了する。 fi /mnt/mtd/hddrootfs.tar.gzと/mnt/mtd/uImage.buffaloの有無の条件分岐を終了する。
https://w.atwiki.jp/aerocats/pages/33.html
標準Linuxの/usr/local/bin/内にある。 HDDの初期化の役割を担う。 ユーザーの意思次第で、開発用LinuxをHDDに設置したりHDDブートするように設定する。 動作内容 スクリプト スクリプト詳細ExitWithError関数 スクリプト本文 デバイスの初期化 動作内容 HDDがマウントされていないことを確認。されていればエラー終了。 HDDがxfs形式でフォーマットされていないことを確認。されていればエラー終了。 /mnt/mtdにChangeMeDevHDDがあるかどうかを確認して以下を実行。 ある場合 HDDを/dev/sda1、/dev/sda2、/dev/sda3、/dev/sda4の4つのパーティションに切り、それぞれをフォーマットする(マウントはしない)。 デバイス フォーマット形式 /dev/sda1 ext3 /dev/sda2 xfs /dev/sda3 swap /dev/sda4 xfs SetupDevEnv.shの実行 /mnt/mtdにhddrootfs.tar.gz、uImage.buffaloがあるかどうかを確認して以下を実行。 ある場合 /mnt/bootディレクトリを作成し、/dev/sda1をext3形式でマウントして、そこにuImage.buffaloをコピーする。 /mnt/rootfsディレクトリを作成し、/dev/sda2をxfs形式でマウントして、そこにhddrootfs.tar.gzを展開する。 デバイス マウントポイント マウントタイプ /dev/sda1 /mnt/boot ext3 /dev/sda2 /mnt/rootfs xfs /usr/local/bin/kuro_libを/mnt/rootfs/usr/local/binにコピーする。 ChangeMyUbootEnvがあればU-Boot環境変数を書き換える。なければそのまま終了する。 ない場合 エラー終了させる。 ない場合 HDDを/dev/sda1と1つだけのパーティション?に切りxfs形式でフォーマットする。 デバイス フォーマット形式 /dev/sda1 xfs /dev/sda1を/mnt/disk1にxfs形式でマウントする。 デバイス マウントポイント マウントタイプ /dev/sda1 /mnt/disk1 xfs /mnt/disk1のパーミッションを777にする。 スクリプト #!/bin/sh . /usr/local/bin/kuro_lib # $1 Error type {mounted | formatted} ExitWithError(){ miconapl -a led_set_cpu_mcon diag miconapl -a led_set_on_off diag miconapl -a led_set_brink diag miconapl -a bz_on on3off3 case $1 in mounted) echo "disk is already mounted!" /dev/console ;; formatted) echo "disk is already formatted!" /dev/console ;; esac sleep 5 miconapl -a bz_on miconapl -a led_set_brink off miconapl -a led_set_on_off off miconapl -a led_set_cpu_mcon off exit 1 } # Check point 1. disk is already mounted or not. IsMounted ${DISK1_DEV} ; [ $? = 1 ] ExitWithError mounted IsMounted ${DISK1_DEV}1 ; [ $? = 1 ] ExitWithError mounted IsMounted ${DISK1_DEV}4 ; [ $? = 1 ] EixtWithError mounted # Check point 2. disk is already formatted or not. XFS_FORMATTED=`dd if=${DISK1_DEV} bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] ExitWithError formatted XFS_FORMATTED=`dd if=${DISK1_DEV}1 bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] ExitWithError formatted XFS_FORMATTED=`dd if=${DISK1_DEV}4 bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] ExitWithError formatted # OK! Disk is not mounted and not formatted. miconapl -a led_set_code_information 28 miconapl -a bz_on button if [ -e ${CHANGE_TO_DEVHDD_FILE} ] ; then fdisk ${DISK1_DEV} /usr/local/bin/PartitionDefinition Format_EXT3 ${DISK1_DEV}1 Format_XFS ${DISK1_DEV}2 Format_XFS ${DISK1_DEV}4 mkswap ${DISK_DEV}3 /usr/local/sbin/SetupDevEnv.sh else fdisk ${DISK1_DEV} /usr/local/bin/PartitionDefinition1 Format_XFS ${DISK1_DEV}1 MountShare ${DISK1_DEV} ${DISK1_MPT} fi miconapl -a led_set_code_information clear ~ # スクリプト詳細 ブロックごとに見てみる。 #!/bin/sh シェルの指定。shを指定している。 . /usr/local/bin/kuro_lib /usr/local/bin/kuro_libをサブシェルで実行している。 このkuro_lib内の InMounted関数 Format_EXT3関数 Format_XFS関数 MountShare関数 IsHavePartition関数 DISK1_DEV変数(=/dev/sda) DISK1_MPT変数(=/mnt/disk1) CHANGE_TO_DEVHDD_FILE変数(=/mnt/mtd/ChangeMeDevHDD) HEXDUMP変数(=/usr/bin/hexdump) を使用するためだ。 ExitWithError関数 関数の定義が始まる。なお、この項目は関数が以後の命令で呼び出された時に機能する内容であり、スクリプト実行と同時に実行されるわけではない。 # $1 Error type {mounted | formatted} ExitWithError(){ 第1引数はmountedかformattedというエラータイプだ、と解説されている。 miconapl -a led_set_cpu_mcon diag miconapl -a led_set_on_off diag miconapl -a led_set_brink diag miconapl -a bz_on on3off3 まずはどのタイプのエラーであれ(この関数が呼び出されている時点で何らかのエラーには間違いないため)、miconaplコマンドでLEDとブザーが共通の操作をされている。 詳しくはmiconaplコマンドで記すが、この4行で エラーLEDが点滅 ブザーがピッピッピと鳴る という動作になる。 case $1 in 先ほどの第1引数の内容によって以後の処理動作を分けている。 第1引数がmountedの場合 mounted) echo "disk is already mounted!" /dev/console ;; echoコマンド?で「disk is already mounted!」という一文がコンソールデバイスに出力されている。 これだけでこのcase文を抜ける。 第1引数がformattedの場合 formatted) echo "disk is already formatted!" /dev/console ;; echoコマンド?で「disk is already formatted!」という一文がコンソールデバイスに出力されている。 これだけでこのcase文を抜ける。 esac 以上の処理でmountedかformattedか、というcase文は終了する。 sleep 5 miconapl -a bz_on miconapl -a led_set_brink off miconapl -a led_set_on_off off miconapl -a led_set_cpu_mcon off 5秒間一時停止した後に、LEDとブザーの動作を止めている。 exit 1 終了ステータスに異常を表す「1」を指定。 } ExitWithError関数はここまで。 スクリプト本文 ここからがいわゆるInitDisk1.shのスクリプト本体だ。 # Check point 1. disk is already mounted or not. まずはチェックポイント1としてHDDがすでにマウントされているかいないかを以下で調査している。 サブシェルで走らせている/usr/local/bin/kuro_lib内の関数「IsMounted」を使うことになる。 ここで述べておく方が理解が容易なので、InitDisk1.shスクリプトの内容ではないが/usr/local/bin/kuro_lib内のIsMounted関数に触れておく。 IsMounted関数 /usr/local/bin/kuro_lib内の関数であり、引数を1つ付けさせて内容により戻り値として「0」か「1」を返す仕組みのようだ。 # $1 device of check target # retval # 1 device $1 is mounted. # 0 device $1 is not mounted. 第1引数はチェック対象のデバイスであり、このIsMounted関数が戻り値1を返せばそのデバイスはマウントされている、0を返せばされていないとする旨の解説だ。 IsMounted(){ MOUNTED=`grep $1 /proc/mounts` MOUNTEDという変数を用意しそこにgrep $1 /proc/mountsの結果を代入している。 $1とはIsMounted関数に付けられた第1引数であり、${DISK1_DEV}すなわち/dev/sdaを指す。 つまり、procコマンド?でマウント状態を調べたとき、/dev/sdaという文字が含まれるものを抽出していることになる。 その結果がMOUNTEDという変数に代入される。 if [ "${MOUNTED}" != "" ] ; then return 1 else return 0 fi このMOUNTED変数がカラでなければ戻り値1を返しIsMounted関数を終了、そうでなければ(カラであれば)0を返しIsMounted関数を終了する、という内容。 この作業で、/dev/sdaがマウントされているかどうかが判別できる。 return 0 上のいずれにもあてはまらなければ(実際にはあり得ないが)0を返す。 } IsMounted関数はここまで。 ここからまたスクリプト本文の解説に戻る。 IsMounted ${DISK1_DEV} ; [ $? = 1 ] ExitWithError mounted IsMounted ${DISK1_DEV}1 ; [ $? = 1 ] ExitWithError mounted IsMounted ${DISK1_DEV}4 ; [ $? = 1 ] EixtWithError mounted IsMounted関数に${DISK1_DEV}(=/dev/sda)、${DISK1_DEV}1(=/dev/sda1)、${DISK1_DEV}4(=/dev/sda4)という引数をそれぞれ付け、戻り値は0か1が返ってくるのを待ち、返って来た結果(戻り値「$?」)が1ならばExitWithError関数をmountedという引数を付けて実行している。 /dev/sdaもしくは/dev/sda1、/dev/sda4のいずれか一つでもマウントされていればInitDisk1.shはエラー終了してしまう、ということだ。 誤動作防止のためだと思われる。 これでチェックポイント1であるマウントされているかどうかの調査は終了する。 # Check point 2. disk is already formatted or not. 次にチェックポイント2としてHDDがすでにフォーマットされているかいないかを以下で調査している。 XFS_FORMATTED=`dd if=${DISK1_DEV} bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] ExitWithError formatted XFS_FORMATTED=`dd if=${DISK1_DEV}1 bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] ExitWithError formatted XFS_FORMATTED=`dd if=${DISK1_DEV}4 bs=1 count=3` ; [ "${XFS_FORMATTED}" = XFS ] ExitWithError formatted 流れとしては XFS_FORMATTEDという変数を用意 そこに対象となるデバイスのフォーマット形式を代入 それがxfs形式かどうかを判別 xfs形式ならばExitWithError関数にformatted引数を付けてエラー処理 となる。 デバイスのフォーマットの調べ方だが、ここではddコマンドで行っている。 ddコマンドのofパラメータは出力先を指すが、今回これは指定しないのですなわち標準出力を指す。 xfs形式でフォーマットされたデバイス(パーティション?)は、 dd if=デバイス bs=1 count=3 とすると XFS3+0 records in 3+0 records out とコンソールには表示されるが、内部的にはXFSの3文字だけが出力されている(of=/mnt/disk1/dd.txtなどで確認してみるとはっきりする)。 ext3ではXFSは表示されないが、XFS形式のものをmkfs.ext3で上書きした場合はXFSと表示されてしまう。 パーティション?の先頭を0で埋めた後、領域を破壊した上でmkfs.ext3を実行しないと機械的にはXFSとみなされるので注意が必要だ。 上の命令は/dev/sda、/dev/sda1、/dev/sda4のいずれかがxfs形式ならばformattedという引数を付けてExitWithError関数を実行(すなわちエラー処理)する、という意味だ。 # OK! Disk is not mounted and not formatted. 以上、2つのチェックポイントを無事通過できると次の処理が待っている。 デバイスの初期化 miconapl -a led_set_code_information 28 miconapl -a bz_on button オレンジのLEDを点滅させ、ブザーをピっと鳴らす。 /mnt/mtdにChangeMeDevHDDがある場合 if [ -e ${CHANGE_TO_DEVHDD_FILE} ] ; then この「-e」という評価式は「存在すれば真」なので、CHANGE_TO_DEVHDD_FILE(/mnt/mtd/にChangeMeDevHDD)が存在すれば以下を実行、という意味になる。 なお、このChangeMeDevHDDとは、附属CD-ROM内にあるもので「HDDパーティション?を開発用に設定するための意思表示ファイル」となっている。中身は何もない。 この条件分岐のためだけにあり、あるかないかが問題なだけだ。 fdisk ${DISK1_DEV} /usr/local/bin/PartitionDefinition /usr/local/bin/PartitionDefinitionに記載されている内容に従って/dev/sdaにパーティション?をきっていく。 記載された内容とは パーティション? サイズ パーティションタイプ /dev/sda1 50MB Linux /dev/sda2 3GB Linux /dev/sda3 128MB swap /dev/sda4 残り Linux となっている。 次に、きられたパーティション?に今度はファイルシステムを導入する。 まずは/usr/local/bin/kuro_lib内の関数「Format_EXT3」を説明する。 Format_EXT3関数 /usr/local/bin/kuro_lib内の関数であり、引数一つを受け取りそのデバイスをext3形式にフォーマットする関数のようだ。 # $1 target device to format Format_EXT3(){ 第1引数のデバイスをフォーマット対象とする。 echo "***** Starting to format $1 *****" 画面に「***** Starting to format 対象デバイス *****」と表示する。 mkfs.ext3 $1 mkfs.ext3コマンド?で第1引数のデバイスをext3形式でフォーマットする。 if [ $? -eq 0 ] ; then $?とは上のmkfs.ext3コマンド?の実行結果の終了ステータスを指しているのだが、これが「0」すなわち成功ならば次を実行、となっている。 echo "Format is succeeded without error." 画面に「Format is succeeded without error.」と表示する。つまり「フォーマットはエラーもなく成功した。」と表示している。 else $?が「0」でなければ、つまりフォーマットに失敗しているのならば次を実行。 return 1 exit 1 fi return 1とは、関数の戻り値を1に明示的に指定してFormat_EXT3関数を終了しているわけだが、このスクリプト内で戻り値を具体的に利用する様子は見受けられないので意味はないだろう。 /usr/local/bin/kuro_libは様々なスクリプトで利用されているライブラリ的なスクリプトなので、どこかで利用するものかもしれない。 exit 1も同じような意味合いだが、終了ステータスを「1」(異常)に設定してスクリプト(/usr/local/bin/kuro_lib)を終了するようにしている。 return 0 戻り値「0」をセットしFormat_EXT3関数を抜ける。 } Format_EXT3関数はここまで。 次に/usr/local/bin/kuro_lib内の関数「Format_XFS」を説明する。 Format_XFS関数 /usr/local/bin/kuro_lib内の関数であり、引数一つを受け取りそのデバイスをxfs形式にフォーマットする関数のようだ。 # $1 target device to format. Format_XFS(){ 第1引数のデバイスをフォーマット対象とする。 KEY=`dd if=$1 bs=1 count=3` KEYという変数を用意し、そこにdd if=$1 bs=1 count=3の結果を代入する。 先ほど検証したようにxfs形式のデバイスに対してこのコマンドを使うと「XFS」と出力される。 if [ "${KEY}" = "XFS" ] ; then KEYの値がXFSならば次を実行、という意味だ。つまりここは対象デバイスのフォーマット形式がxfs形式かどうかを条件分岐にしている。 . /etc/melco/info /etc/melco/infoをサブシェルで走らせているが、標準Linuxにはこのファイルは存在しない。 製品仕様書にも初期化SWの項目に 内蔵HDD(/dev/sda)が既にxfs形式でフォーマットされている場合、フォーマットは行われない。但し、/etc/melco/info内、force_format=yesとすることで、xfsでフォーマットされている/いないにかかわらず、フォーマットを行うようにすることができる。 と記載されている。強制フォーマットの機能を使うのであれば自分で/etc/melco/infoを用意するしかない。 if [ "${force_format}" = "yes" ] ; then /etc/melco/info内の「force_format」項目が「yes」となっていれば以下を実行。 echo "Disk (or partition) is looks like already formatted." echo "If you stop format, Press Ctrl+C in 10 seconds!!!" 画面に「Disk (or partition) is looks like already formatted.If you stop format, Press Ctrl+C in 10 seconds!!!」と表示。 「ディスク(あるいはパーティション?)は既にフォーマットされているようです。フォーマットを中止する場合は10秒以内にCtrl+Cを押してください」という意味。 COUNTER=10 COUNTERという変数を用意し、そこに10を代入。 echo -n "waiting " 画面に「waiting」と表示。-nオプションは「テキストの行末で改行しない」という意味。 while [ ${COUNTER} -gt 0 ] COUNTER変数が0より大きければdo~doneの内容を繰り返す。 do echo -n "." sleep 1 COUNTER=$((${COUNTER} - 1)) done 「waiting」の行末に「.」を表示し、1秒待った後COUNTER変数から1を引く、という内容。 先のwhile条件から、1を引いた結果が0よりも大きければ同じことを繰り返す、ということなので、これで結果的に10秒間待機することになる。 「.」を1秒ごとに表示させるためにwhile文を使ったのだろう。 echo "" echo "OK, go on formatting." echoで空白を表示、これは改行させる目的で、次に「OK, go on formatting.」を表示させている。 else /etc/melco/info内の「force_format」項目が「yes」となっていなければ以下を実行。 return 0 戻り値を「0」に設定しFormat_XFS関数を抜ける。つまりこの関数内の以後の命令は実行しない。 fi fi if [ "${force_format}" = "yes" ]を抜け、すぐ次にif [ "${KEY}" = "XFS" ]も抜けている。 echo "***** Cleaning Disk partition information *****" 画面に「***** Cleaning Disk partition information *****」と表示。 dd if=/dev/zero of=$1 bs=512 count=1 ddコマンドを使ってデバイスの先頭から512バイトに「0」を書き込んでいる。 要するにそのデバイス(パーティション?)を先頭から512バイト分データを消去している。 echo "***** Starting to format $1 *****" 画面に「***** Starting to format 対象デバイス *****」と表示。 mkfs.xfs $1 -f デバイスをmkfs.xfsコマンド?でxfs形式にフォーマットしている。-fは上書きオプション。 if [ $? -eq 0 ] ; then 終了ステータスが0であれば、つまり上のmkfs.xfsコマンド?がエラーでなければ以下を実行。 echo "Format is succeeded without error." 画面に「Format is succeeded without error.」と表示。 else mkfs.xfsでエラーが発生すれば return 1 exit 1 fi 戻り値を1、終了ステータスを1に設定して終了。 return 0 戻り値を0に設定しFormat_XFS関数を抜ける。 } Format_XFS関数はここまで。 これら関数を使ってファイルシステムを導入する命令が以下。 Format_EXT3 ${DISK1_DEV}1 Format_XFS ${DISK1_DEV}2 Format_XFS ${DISK1_DEV}4 mkswap ${DISK_DEV}3 わかりやすく表にすれば デバイス フォーマット形式 /dev/sda1 ext3 /dev/sda2 xfs /dev/sda3 swap /dev/sda4 xfs という意味だが、 mkswap ${DISK_DEV}3 は上のパーティション?の様子からすると mkswap ${DISK1_DEV}3 でなければならないはずだ。開発用Linuxのfstabで/dev/sda3をswapでマウントしようとしても、フォーマットが完了していないため失敗するだろう。 /usr/local/sbin/SetupDevEnv.sh そして、/usr/local/sbin/SetupDevEnv.shを実行する。詳細はSetupDevEnv.shの項目で説明する。 その後、miconapl -a led_set_code_information clearを実行してInitDisk1.shを終了する。 /mnt/mtdにChangeMeDevHDDがない場合 else CHANGE_TO_DEVHDD_FILE(/mnt/mtd/にChangeMeDevHDD)が存在しなければ以下を実行。 fdisk ${DISK1_DEV} /usr/local/bin/PartitionDefinition1 /dev/sdaを/usr/local/bin/PartitionDefinition1に従ってパーティション?分割作業する。 パーティション? サイズ パーティションタイプ /dev/sda1 すべて Linux という内容だ。 Format_XFS ${DISK1_DEV}1 Format_XFS関数で/dev/sda1をxfs形式にフォーマット。 MountShare ${DISK1_DEV} ${DISK1_MPT} MountShare関数に 第1引数 /dev/sda 第2引数 /mnt/disk1 という引数を付けて実行させている。 ここで/usr/local/bin/kuro_lib内のMountShare関数を説明する。 MountShare関数 /usr/local/bin/kuro_lib内の関数。4つまでの引数に対応し、3つの戻り値を設定できる。 # $1 target device to mount. # $2 target mountpoint of $1. # $3 File system of target device(default is xfs). # $4 Mounted device permission(default is 777). MountShare(){ 第1引数にマウントする対象デバイス、第2引数に対象デバイスのマウント先、第3引数に対象デバイスのファイルシステム(初期値はxfs形式)、第4引数にマウントしたデバイスのパーミッション(初期値は777)、という解説。 # ret 0 this is no partition disk. # ret 1 this is nand share type partition # ret 2 this is developkit type partition (maybe) MountShare関数の戻り値ではない。IsHavePartition関数からの戻り値を説明している。 戻り値「0」で「パーティション?が存在しないディスクです」、「1」で「NANDフラッシュ共有時(つまり標準Linux時)のパーティション?です」、「2」で「(おそらく)開発用Linux時のパーティション?です」と、それぞれ意味する。 if [ "$1" = "/dev/sda" -o "$1" = "/dev/sdb" ] ; then 第1引数が/dev/sdaあるいは/dev/sdbであれば以下を実行。 IsHavePartition $1 /usr/local/bin/kuro_lib内のIsHavePartition関数に第1引数を付けて実行している。 ここでIsHavePartition関数を説明する。 IsHavePartition関数 # $1 target device to check partition 第1引数にパーティション状態をチェックする対象デバイス、という解説。 # ret 0 this is no partition disk. # ret 1 this is nand share type partition # ret 2 this is developkit type partition (maybe) 戻り値「0」で「パーティション?が存在しないディスクです」、「1」で「NANDフラッシュ共有時(つまり標準Linux時)のパーティション?です」、「2」で「(おそらく)開発用Linux時のパーティション?です」と、それぞれ意味する。 IsHavePartition(){ if [ -x ${HEXDUMP} ] ; then HEXDUMP変数(=/usr/bin/hexdump)に-xオプションを付けて条件としている。-xオプションは「存在し、かつ実行可能なら真」という意味なので、ここでは「/usr/bin/hexdumpが存在し、かつ実行可能なら次を実行」という意味になる。 DISK_1_PART_TAIL=`hexdump -s 446 -n 64 -e 8/1 "%02x " 2/4 "%10d " "\n" $1 | sed -n "1p"|awk {print $10} ` DISK_1_PART_TAILという変数を用意し、そこにhexdump -s 446 -n 64 -e 8/1 "%02x " 2/4 "%10d " "\n" $1 | sed -n "1p"|awk {print $10} という内容を代入している。 パイプで3つの命令がつながっているが、それぞれに分けて考えてみる。 hexdump hexdump -s 446 -n 64 -e 8/1 "%02x " 2/4 "%10d " "\n" $1 hexdumpコマンドを使っている。先頭から446バイト読み飛ばした所から64バイト分だけを読み込み、それを「8/1 "%02x " 2/4 "%10d " "\n"」というフォーマットで第1引数のデバイスを表示する、という意味になる。 HDDの先頭512バイトはMBR領域となっており、その中の先頭446バイトから64バイトはパーティションテーブルが4エントリ分(1エントリ16バイト)ある。 つまりここでは4つのパーティションテーブルを読み込んだことになる。 次に、詳細はhexdumpコマンドで説明するが、「繰り返し回数/バイト数 "フォーマット"」の羅列がhexdumpコマンドのフォーマット形式なので、この場合は 8回繰り返し/1バイト "フィールド幅2(2桁表示で満たない桁は0で表示)で16進数変換" 2回繰り返し/4バイト "フィールド幅10(10桁表示で満たない桁は空白で表示)で10進数変換" 改行 という内容になる。 つまり、「1バイトづつ8回、4バイトづつ2回、計16バイトを10回にわけて読み込み、それを4行に出力」という内容だ。 パーティションテーブルを1つ読み込んでは改行し、64バイト分すべてを16バイトづつ4行10フィールドで表現している。 4つのパーティション?を切ったHDDで試してみると以下の結果を得た。 00 01 01 00 83 fe 3f 06 63 112392 00 00 01 07 83 fe 7f 74 112455 5879790 00 00 41 75 82 fe 7f 85 5992245 273105 00 00 41 86 83 fe ff ff 6265350 150031035 sed sed -n "1p" 「-n」オプションでhexdumpコマンドから受け取った結果の1行目(pが行を表す)だけを抽出している。 ここの「1p」が「2p」「3p」「4p」と変化していくのは、それぞれパーティションテーブルを1から4まで読み、該当パーティションテーブル以外を破棄している。 先ほどの例で試すと 00 01 01 00 83 fe 3f 06 63 112392 という結果を得る。 awk awk {print $10} sedコマンド?から受け取った行の第10フィールドの値を出力している。 第10フィールドはLBAのパーティション?総セクター数(4バイト)を意味する。 つまり、最終的にDISK_1_PART_TAIL変数に代入したい値とは、各パーティション?の総セクター数であることがわかる。これはhexdumpコマンドで10進数にされている。 DISK_2_PART_TAIL=`hexdump -s 446 -n 64 -e 8/1 "%02x " 2/4 "%10d " "\n" $1 | sed -n "2p"|awk {print $10} ` DISK_3_PART_TAIL=`hexdump -s 446 -n 64 -e 8/1 "%02x " 2/4 "%10d " "\n" $1 | sed -n "3p"|awk {print $10} ` DISK_4_PART_TAIL=`hexdump -s 446 -n 64 -e 8/1 "%02x " 2/4 "%10d " "\n" $1 | sed -n "4p"|awk {print $10} ` 先ほどと同様な処理を各パーティション?ごとにDISK_パーティション番号_PART_TAILという変数に代入している。 例で試すと 112392 という結果。 総セクター数が0であればそのパーティション?は存在しない、という意味になる。 if [ "${DISK_1_PART_TAIL}" -ne 0 -a "${DISK_2_PART_TAIL}" -eq 0 -a "${DISK_3_PART_TAIL}" -eq 0 -a "${DISK_4_PART_TAIL}" -eq 0 ] ; then 第1パーティションの総セクター数が0ではない かつ第2~4パーティションの総セクター数が0 の場合に以下を実行する。 return 1 戻り値「1」を設定し関数を抜ける。 つまり「this is nand share type partition」ということになる。 elif [ "${DISK_1_PART_TAIL}" -ne 0 -a "${DISK_2_PART_TAIL}" -ne 0 -a "${DISK_3_PART_TAIL}" -ne 0 -a "${DISK_4_PART_TAIL}" -ne 0 ] ; then 第1~4パーティションの総セクター数が0ではない の場合に以下を実行。 return 2 戻り値「2」を設定し関数を抜ける。 つまり「this is developkit type partition (maybe)」ということだ。 else それ以外の場合、つまり 第1パーティションの総セクター数が0 の場合に以下を実行。 return 0 戻り値に「0」を設定し関数を抜ける。 つまり「this is no partition disk.」ということになる。 fi パーティション?総セクター数の条件分岐を終了する。 else 「/usr/bin/hexdumpが存在し、かつ実行可能」ではない場合は以下を実行、という意味。 return 0 戻り値に「0」を設定し関数を抜ける。 つまり「this is no partition disk.」ということになる。 fi 「/usr/bin/hexdumpが存在し、かつ実行可能」という条件分岐を終了する。 return 0 いずれにもあてはまらなかった場合、戻り値に「0」を設定し関数を抜ける。 つまり「this is no partition disk.」ということになる。 } IsHavePartition関数はここまで。 ここからまたMountShare関数に戻る。 RET=$? RETという変数を用意し、そこにIsHavePartition関数の戻り値を代入。 [ "${RET}" -eq 1 ] TARGET_DEV=${1}1 [ "${RET}" -eq 2 ] TARGET_DEV=${1}4 [ "${RET}" -eq 0 ] TARGET_DEV=${1} 戻り値が1ならば、TARGET_DEV変数にMountShare関数に付けた第1引数(if文の関係上、/dev/sdaか/dev/sdb)の第1パーティション?を代入する。 戻り値が2ならば、TARGET_DEV変数にMountShare関数に付けた第1引数(if文の関係上、/dev/sdaか/dev/sdb)の第4パーティション?を代入する。 戻り値が0ならば、TARGET_DEV変数にMountShare関数に付けた第1引数(if文の関係上、/dev/sdaか/dev/sdb)を代入する。 というように処理している。 else MountShare関数に付けた第1引数が/dev/sdaでも/dev/sdbでもなければ以下を実行。 TARGET_DEV=$1 TARGET_DEV変数にMountShare関数に付けた第1引数を代入。 fi MountShare関数に付けた第1引数が/dev/sdaか/dev/sdbか、という条件分岐を抜ける。 IsMounted ${TARGET_DEV} IsMounted関数に第1引数としてTARGET_DEV変数を渡す。先ほど説明したとおり、戻り値「1」で「device is mounted.」、戻り値「0」で「device $1 is not mounted.」という意味になる。 if [ $? = 1 ] ; then 戻り値が「1」ならば、つまり「device is mounted.」という意味ならば次を実行。 echo "${TARGET_DEV} is already mounted." 画面上に「対象デバイス is already mounted.」と表示。 return 1 戻り値「1」を設定しMountShare関数を抜ける。 fi IsMounted関数の戻り値による条件分岐を抜ける。 if [ "$3" = "" ] ; then MountShare関数の第3引数が何もなければ以下を実行する。 FS=xfs FSという変数を用意し、そこにxfsを代入する。 else MountShare関数の第3引数に何かあれば以下を実行する。 FS=$3 FSという変数を用意し、そこにその第3引数を代入する。 fi MountShare関数の第3引数の有無の条件分岐を抜ける。 if [ "$4" = "" ] ; then MountShare関数の第4引数が何もなければ以下を実行する。 PERMISSION=777 PERMISSIONという変数を用意し、そこに777を代入する。 else MountShare関数の第4引数に何かあれば以下を実行する。 PERMISSION=$4 PERMISSIONという変数を用意し、そこにその第4引数を代入する。 fi MountShare関数の第4引数の有無の条件分岐を抜ける。 echo "Mounting ${TARGET_DEV} on $2 as a ${FS} file system." 画面上に「Mounting 対象デバイス(MountShare関数の第1引数) on マウントポイント( MountShare関数の第2引数) as a ファイルシステムタイプ(MountShare関数の第3引数) file system.」と表示する。 mount -t ${FS} ${TARGET_DEV} $2 実際に設定した変数の値をもとにmountコマンドでマウントする。 case $? in mountコマンドの終了ステータスをもとに実行内容を変える。 0) 終了ステータス「0」(正常)の場合 chmod ${PERMISSION} $2 echo "Success." ;; chmodコマンド?で設定したパーミッションでマウントポイントのデバイスを指定し、画面上に「Success.」と表示してcase文を抜ける。 *) 終了ステータス「1」(異常)の場合 echo "Failed." return 1 ;; 画面上に「Failed.」と表示して、戻り値「1」を設定しMountShare関数を抜ける。 esac case文はここまで。 echo "" return 0 画面上を改行して戻り値「0」を設定しMountShare関数を抜ける。 } MountShare関数はここまで。 fi CHANGE_TO_DEVHDD_FILE(/mnt/mtd/にChangeMeDevHDD)の有無の条件分岐を抜ける。 miconapl -a led_set_code_information clear LEDの点滅を止める。
https://w.atwiki.jp/aerocats/pages/65.html
BusyBoxとは BusyBoxは多くの標準的なLinuxユーティリティ(コマンド群)を1つの実行可能プログラムとして実装したもの。 それぞれのコマンドが共有する多くの共通要素をまとめることで、数多くのコマンドを備えながら小さな容量におさえることのできた非常に優れたPOSIX準拠プログラム。 なお、BusyBoxにはランレベルの概念はない。 BusyBoxの仕組み BusyBoxが動作する仕組みは比較的簡単で、自分を呼び出した時のプログラム名が動作すべきコマンドだと判断する。 例として「kurobox」という名前でBusyBoxにシンボリックリンクを貼り、PATHの通った場所に置き実行すると、BusyBoxは「kuroboxというコマンドを実行しろ」と命令されたものだと認識する。 main関数のargv[0]が「呼び出したコマンド名」だ。 豊富なコマンド群もほとんどがシンボリックリンクなのでサイズも節約でき、導入も簡単だ。
https://w.atwiki.jp/aerocats/pages/45.html
有料ディストリビューションであるRed Hat Linuxの開発元「Red Hat」が支援するFedora Projectによって開発されている。 半年に一度という驚異的なスピードでバージョンが上がっていく革新的なディストリビューション。 常に最新技術を盛り込むことを開発目的に据え、Linuxで新しいことをするには一番向いているディストリビューションかもしれない。 反面、13ヶ月しかないメンテナンス期間に不満の声もある。 リリースが短期で行われるため「バグが多い」とも言われるが、「Fedoraを使う以上それは承知のうえ」とする声もある。またはそれが楽しい一面なのかもしれない。 Fedora系の特長 Fedoraにもyumコマンドというパッケージ管理ツールが組み込まれている。 書籍などの説明ではこのyumコマンドが多いため、初めてLinuxに触れるのであれば情報量も多く、勉強しやすいディストリビューションだろう。 クライアント用途傾向が強いため、サーバ用途では敬遠されがちだが、使い方次第なので一概には「サーバには不向き」とは言えない。
https://w.atwiki.jp/aerocats/pages/30.html
標準Linuxの/etcディレクトリにあるファイル。 fileコマンド?で調べてみる。 ~ # file /etc/BootFlag file Using regular magic file `/usr/share/magic file couldn t find any magic files! /etc/BootFlag ASCII text テキストファイルであることがわかるので開いてみる。 ~ # cat /etc/BootFlag tftpboot=no tftpboot=noという一文が記述されただけのテキストファイルだ。
https://w.atwiki.jp/aerocats/pages/32.html
半導体メモリには データの読み書きを自由に行なえるが電源を切ると内容が消える「RAM」(Random Access Memory) 一度書き込んだ内容は消去できないが電源を切っても内容が消えない「ROM」(Read Only Memory) の二つがある。 それぞれ「あちらを立てればこちらが立たず」といった関係だが、コンピューター内での用途に見合った性能なのだろう。 データの読み書きが自由にできるRAMには記憶容量としての柔軟さがあるが電源を切れば消えてしまうのがやっかいだし、電源を切っても消えないROMは読み出ししかできない。 フラッシュメモリはこの二つのそれぞれ良いところだけを併せ持っている。 すなわち、「データの読み書きを自由に実現し、電源を切っても内容が消えない(不揮発性)」という性質だ。 価格 一概に記憶媒体の価格を並べても何とも言えないが、参考のため記す。 種類(2008/01/11現在) 容量 価格 円/MB DDR2-SDRAM 1GB 5000 5 USBメモリ 1GB 1300 1.3 HDD(SATA7200rpm) 250GB 12000 0.048 半導体メモリはHDDの容量単価には劣っているが、小型の組み込み機器のような「大容量でなくてもいい」という環境であればサイズ、価格ともにメリットがある。 データを書き込む仕組み
https://w.atwiki.jp/aerocats/pages/58.html
hexdumpコマンドは、あるファイルを指定するフォーマットで出力するフィルターユーティリティだ。 標準Linuxでのhexdumpコマンド 概要 helpを表示してみる。 ~ # hexdump --help BusyBox v1.1.1 (2007.04.06-12 02+0000) multi-call binary Usage hexdump [-[bcCdefnosvx]] [OPTION] FILE The hexdump utility is a filter which displays the specified files, or the standard input, if no files are specified, in a user specified format -b One-byte octal display -c One-byte character display -C Canonical hex+ASCII, 16 bytes per line -d Two-byte decimal display -e FORMAT STRING -f FORMAT FILE -n LENGTH Interpret only length bytes of input -o Two-byte octal display -s OFFSET Skip offset byte -v display all input data -x Two-byte hexadecimal display 標準LinuxでのhexdumpコマンドはBusyBoxが動作する。