PDA

Bekijk de volledige versie : Usage of the pre-* and post-* files in the Oleg's firmware CR9 and above



al37919
02-04-2008, 20:51
In the latest (CR9-10) versions of his firmware Oleg did a lot of efforts to make boot up process more transparent. I can mention pre-mount file which appeared in the CR9 version, and fstab file which appeared a bit earlier, but its usage is still not enough covered in the existing tutorials.

I'd like to admit in advance, that I'm not going to cover usage of the post-firewall, because it stands a bit separately.

Russian speaking part of our community has already had possibility to test these features, as they were available in the post-8 preview versions since late December. So, this topic was already discussed here: http://wl500g.info/showthread.php?t=12221 and the major feedback is already incorporated in it.

/etc/fstab
After 8 months of the usage of wl500g Premium I decided to upgrade my hdd, and partition a new one in a "clever" way. I created the file /etc/fstab with the following content:

#device Mountpoint FStype Options Dump Pass#
/dev/discs/disc0/part1 none swap sw 0 0
/dev/discs/disc0/part2 /opt ext3 rw,noatime 1 1
/dev/discs/disc0/part3 /opt/home ext3 rw,noatime 1 1
/dev/discs/disc0/part4 /home ext3 rw,noatime 1 1
/dev/discs/disc1/part2 /mnt ext3 rw,noatime 1 1
[Last two parameters in every line are not used in our case. So, you can put any.]
[To save the content of the /etc/fstab file in the flashfs do the following:

echo "/etc/fstab >> /usr/local/.files
flashfs save && flashfs commit && flashfs enable
]

The idea of such partitioning was:
/opt --- programs
/home --- archive
/opt/home --- file system for current downloads and other temporary stuff
/mnt --- previous hdd, which will be removed later.

Ideally, one more separate partition can be mounted to /var or /opt/var so that the /opt can be mounted read only. So, the overall reliability of the system can be increased even more, however it's idea for the next upgrade. The most risky file system (from the point of view of possible data loss) is /opt/home. Therefore, it is extracted in a separate and not very big partition. In my system completed downloads are automatically moved to /home, and, if it is necessary to share something, the symlinks in /opt/home are created.

[Remark: if you're going to use /opt/home as a mount point like in this example, don't forget to create this directory first: mkdir /opt/home ]

/usr/local/sbin/pre-mount

The first advantage, which became easily possible with appearance of the pre-mount file --- the routine check of the file systems during boot up.

So, the pre-mount file may look like this:

#! /bin/sh

swapon -a

for i in `awk '/ext3/{print($1)}' /etc/fstab` ; do
if [ -b $i ] ; then
grep -q $i /proc/mounts || e2fsck -p $i 2>&1 | logger -t e2fsck
else
logger -t fstab "$i is not attached"
fi
done
This file performs e2fsck check of every entry of the fstab file, which describes file system of the type ext3 (if such partition is attached to the system).

Why do we need this? Check the log file after rebooting (of course, with suggested pre-mount file):


/dev/discs/disc0/part2: recovering journal
/dev/discs/disc0/part2: clean, 15942/245280 files, 102559/489982 blocks (check after next mount)
/dev/discs/disc0/part3: recovering journal
/dev/discs/disc0/part3: clean, 5141/1835008 files, 1148511/3664828 blocks (check in 5 mounts)
/dev/discs/disc0/part4: recovering journal
/dev/discs/disc0/part4: clean, 73/12517376 files, 3719155/25023245 blocks (check after next mount)
/dev/discs/disc1/part2: recovering journal
/dev/discs/disc1/part2: clean, 36785/2431680 files, 341863/4857654 blocks (check in 2 mounts)

It doesn't looks really nice. It does seem that asus have not done any effort to unmount filesystems on correct shutdown. So, that graceful rebooting using 'halt' or 'restart' and taking off power supply have equal effect. However, if we go with Oleg, then we have a chance to improve situation (using pre-shutdown file).

[Remark: file systems in unix are usually organized in such a way that the full check of the apparently good f.s. is enforced when some conditions are met. It can be either number of mounts, or number of days since last check or something else. With our router (at least most of the models) there is one potential problem --- we don't have RTC, therefore, we obtain time from ntp servers. Some people may find that the disks are checked before obtaining of the correct time. In this case e2fsck will believe that the last check occurred very long ago and enforce full check on every boot up. It may be annoying, because checking of the large partitions may take really looong time. To disable such check by the time since the last check do the following:

tune2fs -i 0 /dev/discs/disc0/part1
to see current settings of the f.s. see:

tune2fs -l /dev/discs/disc0/part1
]
[Remark2: In the latest 10th version of his FW Oleg disabled this check at all so nothing should be done now]

al37919
02-04-2008, 20:55
/usr/local/sbin/pre-shutdown
It should be noted that it is not easy to unmount a file system, when many processes are started in the memory, which possibly access it. However, it can be remounted in the read-only state.

I suggest the following minimalist pre-shutdown:

#! /bin/sh

/opt/etc/init.d/rc.unslung stop

sleep 10s

for i in `cat /proc/mounts | awk '/ext3/{print($1)}'` ; do
mount -oremount,ro $i
done

swapoff -a

sleep 1s

Well, it is still not ideal pre-shutdown. However, the message is: better to have this one, than to have none. I hope better solutions will appear, but more testing and feedback is needed. Our goal is to have all file systems "clean". The good thing is that it is really possible:


/dev/discs/disc0/part2: clean, 15949/245280 files, 102570/489982 blocks
/dev/discs/disc0/part3: clean, 5134/1835008 files, 117343/3664828 blocks (check in 3 mounts)
/dev/discs/disc0/part4: clean, 1320/12517376 files, 5471367/25023245 blocks
/dev/discs/disc1/part2 has been mounted 39 times without being checked, check forced.
/dev/discs/disc1/part2: 36782/2431680 files (7.5% non-contiguous), 341863/4857654 blocks

Now as to the file rc.unslung which is run from pre-shutdown (and post-mount also)
Civilized way of starting daemons is performed traditionally by execution of the file /opt/etc/init.d/rc.unslung, which runs all files located in the directory /opt/etc/init.d, whose name is begun with capital S. These files are installed there automatically by the packages or can be added (and edited) by hand. It is nice to modify the file rc.unslung in such a way that it can not only start these services, but also stop them (ideally, in reverse order). It is especially useful for the programs, which write something to the disk, like torrent clients, amule, etc. Usually SXX* startup scripts for such programs already contain the code necessary to stop them. Some of the program install SXX* startup scripts which are able only to start them. In the latter case they can be either updated or disregarded ;)

So, I suggest the following updated /opt/etc/init.d/rc/unslung which now accepts a single parameter which can be either start or stop:

#! /bin/sh

# Start/stop all init scripts in /opt/etc/init.d
# starting them in numerical order and
# stopping them in reverse numerical order
#
if [ $# -ne 1 ]; then
printf "Usage: $0 {start|stop}\n" >&2
exit 1
fi

daemons=`echo $(/usr/bin/dirname $0)/S??*`
[ $1 = "stop" ] && daemons=`echo $daemons | /usr/bin/tr " " "\n" | /usr/bin/sort -r`

for i in $daemons; do

# Ignore dangling symlinks (if any).
[ ! -f "$i" ] && continue

case "$i" in
*.sh)
# Source shell script for speed.
(
trap - INT QUIT TSTP
set $1
. $i
)
;;
*)
# No sh extension, so fork subprocess.
$i $1
;;
esac
done

I believe that the most appropriate place to start these daemons is post-mount file:

#! /bin/sh

/opt/etc/init.d/rc.unslung start
All the stuff related to mounting can be removed from the post-boot file and now it looks quite elegant:

#! /bin/sh

dropbear
[The usb drivers for external storage can now be loaded (starting from CR9) by a single checkbox in the web interface.]

wengi
03-04-2008, 08:46
Hi,
this is very helpfull. I will link this in my tuts until i updated them.
Thank you :)
wengi

kauczu
05-04-2008, 23:40
Hi there :)

Hard to belive that Asus boxes equiped with original or Oleg's fw are not properly unmounting filesystems, exposing our strorage to corrupt or data loss.
Anyway I used this tutorial and must say: good job! :)

There is one issue: I don't know if it is connected with, but after making changes to files pre* and post* described here, I've noticed that time is not synchronizing witch ntp server directly after boot. In consequence wifi radio did not stand up, because I set webinterface option "Time of Day to Enable Radio" in range 07:00-01:00 :p
So I added:

ntpclient -l -h time.nist.gov -c l -s
line to /usr/local/sbin/pre-mount and now everything is fine.

Thanks! :)

sarlacc
06-04-2008, 00:47
to al37919: I think you should wait for /opt before execution
/opt/etc/init.d/rc.unslung start in .post-mount file!?! In other case nothing happens.

al37919
06-04-2008, 07:46
post-mount is executed after mounting of all filesystems mentioned in fstab, and automounting of those which are not mentioned there.

So waiting gives you nothing.

sarlacc
06-04-2008, 08:42
aha ok, the problem was in the typo error in the name of file rc.unslung thanks.

wengi
25-04-2008, 20:18
Hi there,

i have a prob with starting xinetd.
After installing xinetd with ipkg the file /opt/etc/init.d/S10xinetd is created.

But this file does not work with the start|stop feature of rc.unslung.

So i modified the file.
my /opt/etc/init.d/S10xinetd:
#!/bin/sh
OPTWARE_TARGET=oleg
#
# Startup script for xinetd
#
# Stop myself if running
case $1 in
start)
/opt/sbin/xinetd
;;
stop)
killall xinetd 2>/dev/null

# Stop other inetd processes if running
if [ ${OPTWARE_TARGET} = "nslu2" ] ; then
killall inetd 2>/dev/null
fi
;;
*)

echo "usage: $0 (start|stop)"
exit 1
esac
BUT
If xinetd started smbd and nmbd and is the stopped with "/opt/etc/init.d/S10xinetd stop" the both services (smbd and nmbd) are still running.
Questions:
1) Is this supposed to act this way?
2) could someone please have a look at my version because i am not that good with scripting...

Thanks
wengi

al37919
26-04-2008, 07:38
It seems that it is intended behavior. However we may override it. I suggest to test the following code:

#! /bin/sh
#
# Startup script for xinetd
#
prefix=/opt
sbindir=${prefix}/sbin

NAME=xinetd
DAEMON=${sbindir}/${NAME}
DESC="xinetd"
PIDFILE="/var/run/xinetd.pid"
OPTIONS="-pidfile $PIDFILE"
CONFDIR="/opt/etc/xinetd.d"

# installation check
test -x ${DAEMON} || exit 0

case "$1" in
start)
if [ -z "`pidof ${NAME}`" ] ; then
printf "Starting ${DESC}: "
${DAEMON} ${OPTIONS}
printf "${NAME}.\n"
fi
;;
stop)
if [ -n "`pidof ${NAME}`" ]; then
printf "Stopping ${DESC}: "
kill -SIGTERM `cat $PIDFILE`
printf "${NAME}.\n"
for i in ${CONFDIR}/* ; do
if [ -n "`grep "^[[:space:]]*disable[[:space:]]*=[[:space:]]*no" ${i}`" ] ; then
daemon="`basename $(awk -F= '/^[[:space:]]*server[[:space:]]*=[[:space:]]*.*/{print $2}' ${i})`"
printf "Stopping ${daemon}: "
kill "`pidof ${daemon}`" > /dev/null 2>&1
printf "${daemon}.\n"
fi
done
fi
;;
reload|reconfigure)
if [ -n "`pidof ${NAME}`" ]; then
printf "Reloading ${DESC}: "
kill -SIGHUP `cat $PIDFILE`
printf "${NAME}.\n"
fi
;;
restart|force-reload)
$0 stop
sleep 1
$0 start
;;
*)
printf "Usage: $0 {start|stop|reload|reconfigure|restart|force-reload}\n" >&2
exit
;;
esac

exit 0

wengi
26-04-2008, 08:23
Hi,

isn't this a bit overkill? simply start|stop should be enough...
i made some modifications because there is no pid file in /var/run:

[admin@blechbuechse init.d]$ ./S10xinetd stop
Stopping xinetd: /var/run/xinetd.pid: No such file or directory
./S10xinetd: kill: 45: Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or
kill -l [exitstatus]
xinetd.
Stopping nmbd: nmbd.
Stopping smbd: smbd.
[admin@blechbuechse init.d]

EDIT:
Shame on me. Your version is working very well. My xinetd was simply the old one running without pid file...
Thank you so much!

Thanx
wengi

wengi
26-04-2008, 10:22
Next one is syslog:
Problem with this one
#!/bin/sh
#
# Startup script for syslogd
#
case $1 in
start)
cat /tmp/syslog.log >> /opt/var/log/messages
rm /tmp/syslog.log
ln -s /opt/var/log/messages /tmp/syslog.log
/sbin/syslogd -m 0 -O /opt/var/log/messages -S -l 7
;;
stop)
if [ -n "`pidof syslogd`" ]; then
killall syslogd 2>/dev/null
fi ;;
*)
echo "usage: $0 (start|stop)"
exit 1
esacis that the original syslog is not stopped when the system boots, because there is no kill in the start part.
The symbolic link has to be deleted at stop?

[admin@blechbuechse init.d]$ ps axf
PID TTY STAT TIME COMMAND
1 ? S 0:02 /sbin/init
.
54 ? S 0:00 syslogd -m 0 -O /tmp/syslog.log -S -l 7
.
108 ? S 0:00 /sbin/syslogd -m 0 -O /opt/var/log/messages -S -l 7
.
The best in this case would be to add the kill in the start section. But this would be a restart!
We could add a kill that kills only the original "syslogd -m 0 -O /tmp/syslog.log -S -l 7".

Any hints?

wengi

al37919
26-04-2008, 11:45
I'm not aware of nice solution of this situation. However, I dont see the problem if we do restart it instead of just starting. Anyway two instances of the same syslogd in the memory is a nonsense.

I'm using such piece of code already for a long time:

#!/bin/sh
#
# Startup script for syslog
#
PATH=/opt/bin:/opt/sbin:/opt/local/bin:/sbin:/bin:/usr/bin:/usr/sbin

LOGFILE=syslog.log
KERNLOGFILE=kern.log
LOG_OLD=/tmp
LOG_NEW=/opt/var/log

prefix=""
sbindir=${prefix}/sbin

NAME=syslogd
DAEMON=${sbindir}/${NAME}
DESC="syslogd"
OPTIONS="-m 0 -O $LOG_NEW/$LOGFILE -S -l 6 -s 0"

case "$1" in
start0)
printf "Starting ${DESC}: "
# Copy old syslog and create symlink to new
if [ ! -L /tmp/syslog.log ]; then
cat $LOG_OLD/$LOGFILE >> $LOG_NEW/$LOGFILE
mv $LOG_OLD/$LOGFILE $LOG_NEW/$KERNLOGFILE
ln -s $LOG_NEW/$LOGFILE $LOG_OLD/$LOGFILE
fi
${DAEMON} ${OPTIONS}
printf "${NAME}.\n"
logger -t ${NAME} "started."
;;
stop)
if [ -n "`pidof syslogd`" ]; then
printf "Stopping ${DESC}: "
killall "${NAME}"
printf "${NAME}.\n"
fi
;;
start|restart|force-reload)
$0 stop
sleep 1
$0 start0
;;
*)
printf "Usage: $0 {start|stop|restart|force-reload}\n" >&2
exit
;;
esac

exit 0

By the way, after restarting I set to syslogd loglevel=6 instead of default 7. This allows to clean the log from a lot o annoying useless messages (unfortunately not all). On the other hand transmission users reported that transmission's web-interface wants to see loglevel=7. So, choose whatever you prefer.