Hi everybody. Many apologies for the time it’s taken me to get this post done. Had some bad news this week.
Anyway… On with the festivities…
Fscking With The rc Scripts.
First up – This has very little to do with fsck, the file system checker, I was just being not-very-subtly crude. Also, this section’s not going to be a huge one, as there isn’t a huge amount to modifying the rc scripts beyond what we covered in the previous section.
NOTE: YOU NEED TO BACK UP ANY FILES EDITED IN THIS GUIDE BEFORE TOUCHING THEM. IF YOU DON’T, YOU’RE AN IDIOT AND ARE GOING TO BREAK YOUR PC.
As I mentioned in the first section, the first script to be run is rc.S. This basically contains clauses which run services possibly required for operation of your linux box. As these scripts are extremely generic, there is a lot of what I like to call “crap” in there.
As with the previous guide, start by commenting out or deleting things which are completely irrelevant to the running of your PC, for example if you’re not likely to need LVM (Logical Volume Management) remove the following section:
# Initialize the Logical Volume Manager.
# This won't start unless we find /etc/lvmtab (LVM1) or
# /etc/lvm/backup/ (LVM2). This is created by /sbin/vgscan, so to
# use LVM you must run /sbin/vgscan yourself the first time (and
# create some VGs and LVs).
if [ -r /etc/lvmtab -o -d /etc/lvm/backup ]; then
echo "Initializing LVM (Logical Volume Manager):"
# Check for device-mapper support.
if ! grep -wq device-mapper /proc/devices ; then
# Try to load a device-mapper kernel module:
/sbin/modprobe -q dm-mod
# Scan for new volume groups:
/sbin/vgscan --mknodes --ignorelockingfailure 2> /dev/null
if [ $? = 0 ]; then
# Make volume groups available to the kernel.
# This should also make logical volumes available.
/sbin/vgchange -ay --ignorelockingfailure
Same business with any section you don’t think you’ll be needing. If you’re ever unsure of what a section does, then read up on it. If you still don’t understand after researching it, leave it in.
A few rules
There are a couple of rules to try to stick by once you’ve outright deleted everything that you’re definitely not going to need. The first, as before, is to avoid conditionals. If you need something, make sure it’s executable then remove any check for it’s validity. An example of original code you may need is:
if [ -x /etc/rc.d/rc.modules.local -a -r /proc/modules ]; then
echo "Running /etc/rc.d/rc.modules.local:"
elif [ -x /etc/rc.d/rc.modules-$(uname -r) -a -r /proc/modules ]; then
echo "Running /etc/rc.d/rc.modules-$(uname -r):"
. /etc/rc.d/rc.modules-$(uname -r)
elif [ -x /etc/rc.d/rc.modules -a -r /proc/modules -a -L /etc/rc.d/rc.modules ]$
echo "Running /etc/rc.d/rc.modules -> $(readlink /etc/rc.d/rc.modules):"
elif [ -x /etc/rc.d/rc.modules -a -r /proc/modules ]; then
echo "Running /etc/rc.d/rc.modules:"
This is crap in a couple of ways. Not only does it use nested conditionals to execute the program, but it uses sh to run a script which is unnecessarily huuuuuge for a machine which you can guarantee is built properly and works every time. For this clause, I insert the following:
NEWMODS="$(/usr/bin/find /lib/modules/$RELEASE -mindepth 2 -type f -newer /li$
# Only rebuild dependencies if new module(s) are found:
if [ ! "" = "$NEWMODS" ]; then
echo "Updating module dependencies for Linux $RELEASE:"
echo "Module dependencies up to date (no new kernel modules found)."
/sbin/modprobe agpgart 2> /dev/null
unset NEWMODS RELEASE
WHAT!? I hear you exclaim. Howd’ya reckon that then!?!? I hear you ask. Simply, I have extracted the contents of rc.modules which was of any use at all to me and inserted it directly into rc.S. Bear in mind, this example was for my file server, so didn’t require sound or and bells and whistles. It’s very unlikely that you’ll use exactly this code. I warn you… You will not necessarily have a legible boot script by the time you have finished this. Comment it religiously is my advice.
Another thing you want to try and avoid is piping output. These scripts will never contain anything as dodgy as the following example, but you’ll get the idea.
OUTPUT=`cat /var/log/syslog | grep -i /usr/bin/cron`
Once you see something like this there are a few things you can do with it. First up, remove the redundant cat and specify the location of grep. It will now read:
OUTPUT=`/bin/grep -i /usr/bin/cron /var/log/syslog`
Now check to see if it really needs to search case insensitively. For example, you may have many occurences of /USR/BIN/CRON, but none of /usr/bin/cron. In this case, modify the variable to the following:
OUTPUT=`/bin/grep /USR/BIN/CRON /var/log/syslog`
Now you’ve optimised the variable’s initialisation speed, it’s time to check how many occurences of this variable you have in your script. If you only have one, then remove the variable definition alltogether and replace $OUTPUT in your script with
/bin/grep /USR/BIN/CRON /var/log/syslog
Before I get a tirade of people telling me that what I’ve just said is a pile of horse-crap, I know that these final examples are way exaggerated. No professional would ever include something so ridiculous in their OS, but the point of this article is to get people to think about optimisation, not spoon feed them replacement clauses.
Anyway… If I think of anything else to put in here, I’ll make a revision, but for now I think that this is probably food for thought.
As always, direct any questions/flaming to the comments.