我一直覺得,我還蠻懶惰的,不喜歡做一堆重複的工作,寧願認真做完一次,寫個code,叫電腦自動做,也不願意重複的命令一直打,感覺這種行為很浪費生命,明明自動程序在跑幾秒鐘就沒事了,要燒個一天去做就感覺很白痴。
底下兩段CODE是把當下的UBUNTU或DEBIN系統抽出來做一個ROOTFS,也就是自動做出initrd.img的腳本,用Perl寫這種腳本還蠻快的,而且很好寫,主要是autofs.pl在運作,poCmd.pl是讀取cmd.list內容,讓autofs.pl去呼叫,poCmd.pl會按照cmd.list內列出來的命令,逐一拷貝到/bin底下,順便把需要的動態庫檔案也拷貝進去,後面要把busybox支援的命令在/bin底下做一個soft link,讓系統起來之後有一些基本的命令可以用。
原理就上一篇講的那些做一個自動腳本,把目前的系統抽一個initrd.img的小rootfs出來用,讓系統開機使用RAM DISK的ROOTFS運作,也就是有一些系統商做的小LINUX系統的搞法。
這種系統就是比誰做的小,也就是要做剛好的系統,這有兩個大原則,一個是只載入要用的模組,另外一個是只放需要的命令,所以不要白痴的把所有的模組都放在裏面,也不需要把沒用到的動態函式庫放進去,這樣會讓你做出來的ROOTFS會肥到百M的尺寸,要小,這就需要挑,挑的方法也很簡單,就先看目前系統需要哪些模組,lsmod這個命令可以列出目前系統載入了哪些模組,之後靠modinfo -n去看那個檔案放哪,只抓要用到的東西,另外有些命令用到動態庫,要調用ldd -v 命令去看用了哪些動態庫,只需要拷貝要用到的動態庫就好,這樣才能夠做出比較小的系統,我做出來的initrd.img大概就16M左右,事實上還好沒很肥,反正是自動做的,這大小還可以接受。
本來只是要我做個小系統,讓測試人員可以直接開進去使用,要穩、好拷貝,所以才要我搞這個,我也是努力的花了一星期(含其他案子同時進行)搞出來,下次就開腳本去抽就有了,不需要再來煩我~~XD。
當然不免俗的這程式有BUG(我知道有個問題),有看出來的可以留言,我們討論一下~~XD
poCmd.pl
#!/usr/bin/perl -w
open FH,"<../cmd.list";
foreach my $line(< FH >){
chomp($line);
if($line ne ""){
my $limitCounter=0;
DOAGAIN:
my @paths=("/bin/","/sbin/","/usr/bin/","/usr/sbin/");
print "$line";
my $found=0;
foreach my $path(@paths){
if(-e "$path$line"){
print "\t- $path$line\n";
system "cp $path$line bin/.";
my @vars=`ldd -v $path$line | grep lib | grep :\$ | cut -d ':' -f 1`;
foreach my $var(@vars){
chomp($var);
$var =~ s/\t//g;
$var =~ s/\ //g;
print "\t$var\n";
my $libPath="lib/.";
#$libPath = "lib64/." if($var =~ /x86\_64/i);
system "cp $var $libPath";
}
$found = 1;
$limitCounter=0;
last;
}
}
if($found == 0){
print "Can't found command exist!";
system "sudo apt-get install $line";
exit 1 if($limitCounter >= 3);
$limitCounter++;
goto DOAGAIN;
}
}
}
close FH;
#process busybox softlink
print "make busybox command list\n";
chdir "bin/";
my @vars = `busybox | grep \,\ `;
foreach my $var (@vars){
if($var !~ /copyright/i){
chomp($var);
$var =~ s/\ //g;
$var =~ s/\t//g;
my @cmds = split /\,/,$var;
foreach my $cmd(@cmds){
if($cmd !~ /\[/){
print "[busybox command]\t$cmd\n";
system "ln -s busybox $cmd";
}
}
}
}
autofs.pl
#!/usr/bin/perl -w
use File::Basename;
#Auto make rootfs on Debin/Ubuntu
#Author Jones
print "Auto make rootfs for Debin/Ubuntu\n";
print "Author Jones Lai\n";
my $var = `uname -a`;
if(($var !~ /ubuntu/i)&&($var !~ /debin/i)){
print "This script just made for Debin/Ubuntu\n";
exit 1;
}
$var = `dpkg -l`;
if($var !~ /build\-essential/){
print "Require build-essential\r\n";
system "sudo apt-get install build-essential";
}
my @kernels = `ls /lib/modules/`;
@kernels = sort {$b cmp $a} @kernels;
my $lastKernel = $kernels[0];
chomp($lastKernel);
print "Last kernel version is $lastKernel\n";
if(!(-e "vmlinuz")){
print "copy kernel to local\n";
system "cp /boot/vmlinuz-$lastKernel ./vmlinuz";
}
if(!(-e "initrd.img")){
system "mkinitramfs -o initrd.img $lastKernel";
}
if(!(-e "tmp")){
system "mkdir tmp";
}else{
system "rm tmp/ -fr";
system "mkdir tmp";
}
chdir "tmp/";
system "gunzip < ../initrd.img | cpio --extract --preserve --verbose --no-absolute-filenames";
my @modules = `lsmod`;
open(FH,">conf/modules");
foreach my $module(@modules){
chomp($module);
next if($module =~ /module/i);
my ($MOD,$others) = split /\ +/,$module;
print FH "$MOD\n";
my $var = `modinfo -n $MOD`;
chomp($var);
my $dirname = dirname($var);
system "mkdir -p .$dirname/\n";
system "cp -p $var .$var\n";
print "[copy module]: $var\n";
}
close(FH);
system "perl ../poCmd.pl";
system "cp ../init init";
system "chmod +x init";
$var = `find . | cpio --create --format='newc' > ../newinitrd`;
print "$var\n";
$var = `gzip ../newinitrd`;
print "$var\n";
$var = `mv ../newinitrd.gz ../newinitrd.img`;
print "$var";
$var = `rm ../initrd.img` if(-e "../initrd.img");
$var = `mv ../newinitrd.img ../initrd.img`;
chdir "../";