☆os-proberでsda10がsda2の前に出てくるのを直す

私はパーティションを制限いっぱいの16まで切っています。
これで困るのは、grub-updateで作成される/boot/grub/grub.cfgのmenuentryの順序です。
grub2のOS選択画面で/dev/sda2のUbuntuより先に/dev/sda10や/dev/sda11が先に表示されてしまいます。
30_os-proberのセクションではos-proberの出力順にしたがってmenuentryが作成されるので、
修正すべきはos-proberの出力順序です。

os-proberの中をのぞいてみるとpartitionsというシェル関数で"/sys/block/*/*[0-9]"という記述があります。
シェルのグロビングのソートは文字列の昇順なので、ここが原因だとわかります。
コマンドの性質上(障害時などは/usrがマウントされない可能性がある)、
スタティックリンクされた/bin,/sbinの下にあるバイナリだけを使用して処理を記述すべきです。
そうするとsortは使えません。もちろんawkやperlもダメです。
ちょっとしたパズル感覚です。

2010/05/22追記
スタティックリンクされたバイナリは/bin/busyboxと/sbin/ldconfig.realだけでした。
しかもbusyboxにはawkやsortも組み込まれています....

幸いsh(dash)のビルトインにprintfがあったので、sed,printf,シェルのグロビングのあわせ技でソートしてみました。
パッチはこれ os-prober.patch です。
tail_num_sortは/usr/share/os-prober/common.shに追加することも考えたのですが、 自分しか使わないと思ったのでos-proberに入れてしまいました。

しかし、Lucidになってからmenuentryの文字列が長すぎです。
OS選択画面でパーティションの部分が見えなくなってしまいました。
仕方がないので"e"を押してどのパーティションか確認してからCtrl+xで起動しています。

修正前のos-proberの出力
/dev/sda10:Ubuntu 10.04 LTS (10.04):Ubuntu:linux
/dev/sda11:Ubuntu 10.04 LTS (10.04):Ubuntu1:linux
/dev/sda2:Ubuntu 9.10 (9.10):Ubuntu2:linux
/dev/sda3:Ubuntu 9.10 (9.10):Ubuntu3:linux
/dev/sda5:Ubuntu 10.04 LTS (10.04):Ubuntu4:linux
/dev/sda6:Ubuntu 10.04 LTS (10.04):Ubuntu5:linux
/dev/sda7:Ubuntu lucid (development branch) (10.04):Ubuntu6:linux
/dev/sda8:Ubuntu 10.04 LTS (10.04):Ubuntu7:linux
/dev/sda9:Ubuntu 10.04 LTS (10.04):Ubuntu8:linux
修正後のos-proberの出力
/dev/sda2:Ubuntu 9.10 (9.10):Ubuntu:linux
/dev/sda3:Ubuntu 9.10 (9.10):Ubuntu1:linux
/dev/sda5:Ubuntu 10.04 LTS (10.04):Ubuntu2:linux
/dev/sda6:Ubuntu 10.04 LTS (10.04):Ubuntu3:linux
/dev/sda7:Ubuntu lucid (development branch) (10.04):Ubuntu4:linux
/dev/sda8:Ubuntu 10.04 LTS (10.04):Ubuntu5:linux
/dev/sda9:Ubuntu 10.04 LTS (10.04):Ubuntu6:linux
/dev/sda10:Ubuntu 10.04 LTS (10.04):Ubuntu7:linux
/dev/sda11:Ubuntu 10.04 LTS (10.04):Ubuntu8:linux
os-prober.patch
diff -ru a/os-prober b/os-prober
--- a/os-prober 2010-02-11 08:06:58.000000000 +0900
+++ b/os-prober 2010-05-04 21:45:47.261264519 +0900
@@ -24,12 +24,32 @@
  return 1
 }
 
+tail_num_sort() {
+ if [ $# -eq 0 ] ; then
+  return 0
+ fi
+
+ if type mktemp >/dev/null 2>&1; then
+  TAILNUMSORT_TMP="$(mktemp -d /tmp/tailnumsort.XXXXXX)"
+ else
+  TAILNUMSORT_TMP=/tmp/tailnumsort.$$
+ fi
+ trap "rm -rf $TAILNUMSORT_TMP" EXIT HUP INT QUIT TERM
+
+ for dev in $@ ; do
+  disk=$(echo $dev | sed -e 's#/##g;s#[0-9]*[0-9]*$##')
+  fname=$(printf '%s%02d' $disk $(echo $dev | sed -e "s#/##g;s#$disk##"))
+  echo $dev > $TAILNUMSORT_TMP/$fname
+ done
+ cat $TAILNUMSORT_TMP/* 2>/dev/null
+}
+
 partitions () {
  # Exclude partitions that have whole_disk sysfs attribute set.
  if [ -d /sys/block ]; then
   # Exclude partitions on physical disks that are part of a
   # Serial ATA RAID disk.
-  for part in /sys/block/*/*[0-9]; do
+  for part in $(tail_num_sort /sys/block/*/*[0-9]); do
    if [ -f "$part/start" ] && \
       [ ! -f "$part/whole_disk" ] && ! on_sataraid $part; then
     name="$(echo "${part##*/}" | sed 's,[!.],/,g')"

0 件のコメント:

コメントを投稿