While experimenting with building kernel 2.6.2, modifying the initialization scripts caused some confusion that I hope someone here can clarify for me. (I realize this pertains to programming; however, the programming forum here is in the non-Linux section, and since this is a Linux-specific issue I thought that I should put it here.)
I wanted to modify rc.sysinit and halt, as outlined on several web sites related to 2.6 migration, but since I still have kernel 2.4.20-8 [Redhat 9.0 (Shrike)] on the machine, I didn't want to tamper with the original (2.4) scripts. Thus, I moved rc.sysinit to rc.sysinit.2.4 and copied it to rc.sysinit.2.6 for specialization (mounting sysfs, etc.). For rc.sysinit, I wrote the following script:
Code:
#!/bin/bash
KERNEL=$(uname -r | awk -F. '{print $1"."$2}')
if [ $KERNEL = "2.6" ]; then
. /etc/rc.d/rc.sysinit.2.6
else
. /etc/rc.d/rc.sysinit.2.4
fi
This worked like a charm. (Of course, booting into 2.4 complained about the sysfs entry in fstab... But that's beside the point.)
I naively decided to try the same with the halt script (/etc/rc.d/init.d/halt) to change
Code:
awk '$2 ~ /^\/$|^\/proc|^\/dev/{next}
$3 == "tmpfs" || $3 == "proc" {print $2 ; next}
/(^#|loopfs|autofs|devfs|^none|^\/dev\/root)/ {next}
{print $2}' /proc/mounts
to
Code:
awk '$2 ~ /^\/$|^\/proc|^\/sys|^\/dev/{next}
$3 == "tmpfs" || $3 == "proc" {print $2 ; next}
/(^#|loopfs|autofs|devfs|^none|^\/dev\/root)/ {next}
{print $2}' /proc/mounts
in the 2.6 version.
This didn't seem to cause any problems with rebooting or shutting down for either version of the kernel.
However, upon later study of the halt scripts, I found the following:
Code:
# See how we were called.
case "$0" in
*halt)
message=$"Halting system..."
command="/sbin/halt"
;;
*reboot)
message=$"Please stand by while rebooting the system..."
command="/sbin/reboot"
;;
*)
echo $"$0: call me as 'halt' or 'reboot' please!"
exit 1
;;
(Of course, the end of the script calls command.)
Why didn't the halt script fail? How did it know whether to reboot or shut down? What would the machine do on failure? I didn't pass the command line from halt to halt.2.4 or halt.2.6! (I don't even remember seeing the warning. I should probably try it again to confirm it for myself, but I don't want to risk putting the system into an unstable state, now that I realize the logic error.)
I made some simple test scripts to review how shell scripts pass command-line arguments.
Script: test...
Code:
#!/bin/bash
./test2 "$@"
Script: test2...
Code:
#!/bin/bash
echo "$0"
echo "$1"
echo "$2"
Running
./test -r -t.
-- random arguments -- gave me,
./test2
-r
-t
Therefore, this method wouldn't fix the [nonexistent] problem. Running halt or reboot from kernel 2.6 should result in $0=halt.2.6 for halt.2.6, which should choke the script. Am I missing something?
(I think I even rebooted with the command-line passing with no negative symptoms, but I can't say for sure that I did.)
I started to think that rebooting and shutting down from X11 didn't execute the halt script, so I added
Code:
echo $"Running halt script..."
to the original script and rebooted. Sure enough, the console showed "Running halt script..." before rebooting.
I decided to restore the original halt script and handle the change with a uname -r test within the script (sloppy, in my opinion)...
But I'd still like to understand this seemingly strange behavior. Does anyone understand what is happening here?
UPDATE:
Putting echo "$0" in the halt script revealed that /etc/rc0.d/S01halt and /etc/rc6.d/S06reboot link to /etc/rc.d/init.d/halt and halt somehow sees the respective path in $0.
I replaced halt with the "forking" script and tried echo "$0" in halt.2.4, and again echo reported the path to S06reboot on reboot..
Thus, I have an answer to why the halt script doesn't fail to shut down or reboot the machine. I just don't know how it sees what it sees, when the test bash script (above) would indicate otherwise.
Anyone?
For anyone who wants to maintain both 2.4 and 2.6 kernels, here's the working /etc/rc.d/init.d/halt script:
Code:
#!/bin/bash
KERNEL=$(uname -r | awk -F. '{print $1"."$2}')
if [ $KERNEL = "2.6" ]; then
. /etc/init.d/halt.2.6
else
. /etc/init.d/halt.2.4
fi
(See descriptions of halt.2.4 and halt.2.6 above.)
SOLUTION:
I found the answer. My test script didn't have a leading '.' before the call to test2. Furthermore, invoked from a symbolic link to test $0 holds the name of the symbolic link. Problem solved. What a difference a "dot" makes.