Chinaunix首页 | 论坛 | 博客
  • 博客访问: 805104
  • 博文数量: 330
  • 博客积分: 9641
  • 博客等级: 中将
  • 技术积分: 3181
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
文章分类

全部博文(330)

文章存档

2012年(17)

2011年(135)

2010年(85)

2009年(57)

2008年(36)

我的朋友

分类:

2008-11-23 13:31:10

http://blog.sina.com.cn/s/blog_4707c927010007a4.html

Without doubt, one of Gentoo's best features is its package management system, Portage. Portage makes it very easy to update your entire system with one simple command. Sadly, things don't always go as smooth as they should. Almost every Gentoo user has typed emerge -uD world and gone to bed with the hope of waking up in the morning to a completely up to date system. Unfortunately, it's more likely that you.ll wake up to a failed emerge on package 3 of 220. And so the troubleshoot and emerge --resume process begins.

Enter update-world to save the day. Update-world is a bash script that was recently created by count_zero and in the forums. The script controls the update process and forces portage to skip past failed builds and continue compiling packages until the update list is finished. Failed builds are added to a list for review once the update is finished.

Note: The script does depend on the 'equery' command, part of app-portage/gentoolkit.

Obviously before you can start using the script, you'll need to download it, put it somewhere in your path, and make it executable.

Code Listing 3.1: getting the script

# wget -O /usr/bin/update-world 
# chmod +x /usr/bin/update-world

Now we're ready to start using the script.

Code Listing 3.2: running update-world

# update-world --prepare

This begins the update process by creating a list of packages to be emerged, as produced by emerge -uD --newuse world. (Alternatively, you can use update-world --empty to create a list of all packages on the system, akin to emerge -e world). This command creates a list called 'emergelist' in ~/.update-world/. Now, you can use your favorite editor to modify this list how you like--remove packages, change versions, etc. When you have the emergelist how you like it, you're ready to move onto the next step:

Code Listing 3.3: running update-world (cont)

# update-world --install

This command actually starts the build process, just as if you had typed emerge -uD world. The difference is, if a package fails for some reason or another, that package is added to a list 'failedlist' in ~/.update-world/. Also, a link to the portage log file for that package (usually located in /var/log/portage) is created in ~/.update-world/[date]/log/. Once the process is done, you'll be presented with a list of failed packages to take care of all at once, saving much time. If you ever need to stop the process, just hit 'Control-C' to abort the process. The update can then be restarted at any time, just where it left off, by retyping update-world --install.

代码如下:

#!/bin/bash
# update-world 1.5
# count_zero 2006
# Licensed under the GPLv2
#
# update-world is a bash script that forces an emerge -uD world to continue, even
# in the face of (inevitable) compile failures.  Failed builds are added to a list,
# and the script jumps to the next package in the queue.
#
# just run update-world --prepare (or --empty) followed by update-world --install.
#
# Release Notes:
# v1.5: now handles 'fetch restriction' properly
# v1.4: uses '--newuse' for emerges to respect new use flags
# v1.3: uses '--oneshot' for emerges so they don't get added to the world file.
# v1.2: Script now detects log directly instead of accepting only /var/log/portage
# v1.1: minor bugfix to allow package without version to be added to 'emergelist'
# v1.0: Release
#
#
# Set the program directory and important variables
homedir=~/.update-world
workdir="$homedir/`date +%F`"
logdir="$workdir/log"
mkdir -p $logdir
touch $homedir/failedlist
emergelist=$homedir/emergelist
emergetemp=$workdir/emergetemp
failedlist=$homedir/failedlist
portlogdir=`cat /etc/make.conf | grep PORT_LOGDIR | sed 's/PORT_LOGDIR=//' | sed 's/\"//g' | sed 's/\/$//'`
masked=$homedir/masked
# parameter for '--empty' to emerge -e world
if [[ $1 == '--empty' || $1 == '-e' ]]
   then parameter='-pev'
   else parameter='-puvD --newuse'
fi
#### update-world --prepare ####
# Prepare the list of packages to emerge into emerglist
if [[ $1 == "--prepare" || $1 == "-p" || $1 == '--empty' || $1 == '-e' ]]
   then
   if [[ -e $emergelist ]]
      then echo -n "The file 'emergelist' already exists and will be overwritten.
Continue anyway? (y/n) "
      read continue
      if [[ $continue == 'y' || $continue == 'yes' || $continue == 'Y' || $continue == 'Yes' || $continue == 'YES' || $continue == '' ]]
         then :
         else echo exiting.
         exit 0
      fi
      else :
   fi
   emerge $parameter world | tee $emergelist
   # Make sure there are no errors in the emerge process
echo
   if grep -q "blocks B " $emergelist
      then echo "WARNING: You have a blocking package.  Fix this before continuing."
      rm -f $emergelist
      exit 1
      elif grep -q "masked" $emergelist
      then echo "WARNING: You need to unmask some packages before continuing."
      rm -f $emergelist
      exit 1
      elif grep -q "emerge: there are no ebuilds to satisfy" $emergelist
      then echo "WARNING: One of the specified packages doesn't exist"
      rm -f $emergelist
      exit 1
      elif grep -q 'Fetch Restriction' $emergelist
      then fetchrestricted=`cat $emergelist | grep ^[[]ebuild[A-Za-z\ ]*F[A-Za-z\ ]*[]] | grep -o []][a-zA-Z0-9\/.\ -]*[[] | sed 's/\]\ //'  | sed 's/\ \[//'`
      echo "WARNING: The following packages have Fetch Restriction turned on:
$fetchrestricted

Please download the sources from the location specified in the ebuild to /usr/portage/distfiles/ and rerun this script."
      exit 1
      else :
   fi
   echo "
These are the packages that will be installed.  If you want to alter this list,
just edit the file 'emergelist' in $homedir. When finished, run
'update-world --install'"
   cat $emergelist | sed '/^[TC]/d' | sed 's/\[ebuild.*[ A-Z]\]\ //' | sed '/^[ ]/d' | sed '/^[ ]*$/d' | sed '/Portage\ overlays/d' | sed 's/\ .*$//' | sort -d | sed 's/.*/\=&/' > $emergetemp
   mv $emergetemp $emergelist
   rm -f $failedlist
   exit 0
#### update-world --install ####
# Install the packages listed in emergelist
elif [[ $1 == "--install" || $1 == "-i" ]]
   then
   # Verify that the emergelist doesn't produce errors
   cat $emergelist | xargs emerge -p > $emergetemp
   if grep -q "blocks B " $emergetemp
      then echo "WARNING: You have a blocking package.  Fix this before continuing."
      rm -f $emergetemp
      exit 1
      elif grep -q "masked" $emergelist
      then echo "WARNING: You need to unmask some packages before continuing."
      rm -f $emergetemp
      exit 1
      elif grep -q "emerge: there are no ebuilds to satisfy" $emergelist
      then echo "WARNING: One of the specified packages doesn't exist"
      rm -f $emergetemp
      exit 1
      elif [[ -z `cat $emergelist` ]]
      then echo "WARNING: no 'emergelist' exists.  Did you run 'update-world --prepare' first?"
      rm -f $emergetemp
      exit 1
      else :
   fi
   # Until loop to make portage continue until finished
   increment=0
   until [[ $increment == 1 ]]
   do
      cat $emergelist | xargs emerge -1
      # Detect which packages have been successfully emerged and remove from the queue
      installed=`tac /var/log/emerge.log | sed '/Started\ emerge/,$d' | grep "completed emerge" | sed 's/^.*)\ //' | sed 's/\ to.*//'`
      for each in $installed
      do
         eachsed=`echo $each | sed 's|\/|\\\/|'`
         if [[ -z `cat $emergelist | grep $each` ]]
            then eachsed=`echo $eachsed | sed 's/\-[0-9].*//'`
            else :
         fi
         cat $emergelist | sed "/$eachsed/d" > $emergetemp
         mv $emergetemp $emergelist
      done
      # See if all packages have been emerged
      if [[ -z `cat $emergelist` ]]
         then increment=1
         else :
      fi
      if [[ $increment == 0 ]]
      then
      errorlog=`ls -t $portlogdir | sed '2,$d'`
      if [[ -n `cat $portlogdir/$errorlog | grep 'signal 2'` ]]
         then echo "
*** User hit 'Control-C' ... exiting.
"
         exit 1
         else :
      fi
      sleep 5
      echo
      echo "*** Hit Control-C to exit, or just wait to continue with emerge."
      echo
      sleep 10
      echo "*** Continuing with emerge."
      # Detect failed emerge and add to failedlist, remove failed package from emergelist
      failedpkg=`tac /var/log/emerge.log | sed '1d' | sed '/terminating/,$d' | sed '/completed\ emerge/,$d' | grep ">>>" | sed 's/.*)\ //' | sed 's/\ to.*//'`
      if [[ -n `tail -n 1 $failedlist | grep $failedpkg` ]]
         then echo "The failed package $failedpkg could not be merged and must be successfully installed before continuing."
         exit 1
         else :
      fi
      echo $failedpkg >> $failedlist
      failedpkgsed=`echo $failedpkg | sed 's|\/|\\\/|'`
      cat $emergelist | sed "/$failedpkgsed/d" > $emergetemp
      mv $emergetemp $emergelist
      ln -s $portlogdir/$errorlog $logdir/${errorlog}_error-log
      echo
      echo
      echo "*** $failedpkg compile failed, skipping."
      # Is there a package in 'emergelist' that requires the failed pkg as a dep? If so, remove it too.
      failedpkgdeps=`echo $failedpkg | sed 's/-[0-9].*//'`
      deps=`equery depends $failedpkgdeps | sed '/^\[/d' | sed 's/-[0-9].*//'`
      for each in `echo $deps`
      do
         if [[ -n `cat $emergelist | grep "$each"` ]]
            then
            if [[ -n `emerge -p $each | grep "$failedpkg"` ]]
               then
               each2=`cat $emergelist | grep $each | sed 's/\=//'`
               echo "$each2 (depends on $failedpkg)" >> $failedlist
               eachsed=`echo $each | sed 's|\/|\\\/|'`
               cat $emergelist | sed "/$eachsed/d" > $emergetemp
               mv $emergetemp $emergelist
               echo "*** $each depends on $failedpkg, skipping."
               else :
            fi
            else :
         fi
      done
      echo "*** Continuing with emerge world"
      else :
      fi
   done
# if improper argument is given to 'update-world' display the help text
else echo "update-world 1.0
count_zero 2006
licensed under the GPLv2

Description:
This is a bash script to automate the 'emerge -uD world' process.
Its purpose is to make updating the system as hands-free as possible.
It does this by automatically recovering from a failed emerge and moving
on to the next one, presenting the user with a list of failed packages
once the update has finished.  No more 'babysitting' the update process!
Just start it, and deal with any failed packages at the end.  Log files
from the failed emerges are saved in the log directory.

The default program directory is ~/.update-world

Usage:
update-world [--prepare | -p ]
   Prepares a list of packages produced by 'emerge -puvD world'
   and outputs them to the file 'emergelist' in the current directory.
   Add, remove, or change the version of any of the packages listed
   in this file with your favorite editor before continuing.
update-world [--empty | -e ]
   Same as --prepare except it performs 'emerge -ev world' to recompile
   all packages on a system.
update-world [--install | -i ]
   Begins the emerge process based upon the 'emergelist' file created
   from running 'update-world --prepare'.  Once finished, failed builds
   will be saved in the file 'failedlist' in the current directory."
exit 1
fi


echo "Congratulations!  'emerge world' complete."
echo
# All done! display the failed packages, if any
if [[ -z `cat $failedlist` ]]
   then echo "All packages emerged successfully"
   else echo "These packages couldn't be merged due to compile errors:"
   echo
   cat $failedlist
   echo
   echo "Look in $logdir/ for the portage log files of the failed builds.
Check bugs.gentoo.org or the Gentoo Forums for help."
fi
exit 0

阅读(1296) | 评论(0) | 转发(0) |
0

上一篇:font configuration

下一篇:GWN心得技巧摘录

给主人留下些什么吧!~~