Dual-Boot challenges Edit
Other pages on the Wiki, e.g. Converting Distributions, and external sources (such as this support page) describe how to switch from running Linux natively using a partition (or several partitions) to running coLinux using these partitions. But what if we wish to do both?
There are several significant differences between what we have to do when we boot our Linux in stand-alone mode and in coLinux mode:
- The devices for the 'Linux-related' filesystems change (e.g. instead of `/dev/sda1` we may have `/dev/cobd0`)
- Instead of being able to mount the 'Windows-related' partitions directly, as vfat or msdos or ntfs type partitions, we must mount them either using Samba or as COFS devices).
- The coLinux system is to be considered as a different machine than the Windows host, e.g. it needs a distinct hostname and IP address (because if you boot Linux directly you usually use the same hostnmane and IP address as in Windows)
- Some additional network-related settings may differ, depending on whether you're using a bridged or a NATed connection
- You may want your X display manager (e.g. xdm, gdm or kdm) to act differently - when booting natively it would run an X server on the Linux machine, and when booting in coLinux mode, it might, say, listen for XDMCP queries. Or you may want an X display manager + X server when booting natively but a VNC X Server when running in coLinux mode, so that you may connect to it using a VNC client.
Making these configuration changes is, again, covered by other pages; the question is how, when our Linux is booting, do we determine whether we're running in coLinux or natively, and how do we automatically and dynamically modify the configuration files so that the rest of the boot process will reflect our required choice in each of the abovementioned issues.
Three possible solution schemes seem possible:
- Setting symlinks, i.e. something like the Debian 'alternatives' system
- Same as the above, but overwriting configuration files with relevant versions instead of symlinking
- Parsing proto-configuration files, and dynamically generating the configuration files from them.
All of these are to be applied using the init script/s which run right after the basic boot process is complete and before entering the initial runlevel.
Here is how Debian defines its alternatives system:
> It is possible for several programs fulfilling the same or similar > functions to be installed on a single system at the same time. For > example, many systems have several text editors installed at once. > This gives choice to the users of a system, allowing each to use a dif- > ferent editor, if desired, but makes it difficult for a program to make > a good choice of editor to invoke if the user has not specified a par- > ticular preference. > > Debian's alternatives system aims to solve this problem. A generic > name in the filesystem is shared by all files providing interchangeable > functionality. The alternatives system and the system administrator > together determine which actual file is referenced by this generic > name. For example, if the text editors ed(1) and nvi(1) are both > installed on the system, the alternatives system will cause the generic > name /usr/bin/editor to refer to /usr/bin/nvi by default. The system > administrator can override this and cause it to refer to /usr/bin/ed > instead, and the alternatives system will not alter this setting until > explicitly requested to do so. > > The generic name is not a direct symbolic link to the selected alterna- > tive. Instead, it is a symbolic link to a name in the alternatives > directory, which in turn is a symbolic link to the actual file refer- > enced. This is done so that the system administrator's changes can be > confined within the /etc directory: the FHS (q.v.) gives reasons why > this is a Good Thing.
This solution is not very robust, since if you upgrade your system in some way, you will have to manually update both versions of your configuration files (and possibly propagate some changes which were made automatically to your current configuration files).
The symlinks option has the added 'uncertainty factor' of relying on symlinks in general, and the possibility that some process or user will change the 'active' version of the configuration file, permanently changing one of the two 'master' versions.
Overwriting Scripts Edit
Here is a sample startup script which overrides some configuration files with one of the two relevant versions. It is a Debian script; in Debian, have it run by linking to it from `/etc/rcS.d/` , and use a priority such that it runs after the root fs becomes writable, but before the rest of the local filesystems are mounted. With other distributions, you may need to make some adaptations to it.
# # colinux use either a set of coLinux-related configuration # files, or their direct-boot counterparts # # if [[ $COLINUX ]]; then SUFFIX=colinux else SUFFIX=non-colinux fi for conf_file in \ "/etc/fstab" \ "/etc/network/interfaces" \ "/etc/X11/gdm/gdm.conf" \ "/etc/hostname" \ "/etc/mailname" \ ; do cp -f $conf_file-$SUFFIX $conf_file done # the COLINUX environment variable is not inherited much further # than the init scripts, so if you want user processes to be able # to tell whether we're in coLinux or stand-alone mode, you could # do something like # echo $COLINUX > /var/local/colinux # or have the file's existence be the thing to check: #if [[ $COLINUX ]]; then #touch /var/local/colinux #else #rm -f /var/local/colinux #fi : exit 0
Obviously, you're asking yourself who sets the `COLINUX` environment variable. Well, you do! In your coLinux configuration file, have a bootprompt line such as the following:
(you may have other parameters, you just need to set the `COLINUX` value).
As for the settings files themselves - these will differ based on exactly what you're configuring, as well as difference between distributions.
Dynamic Parser/Generator Scripts Edit
Using scripts to dynamically to generate configuration files has both potential pros and cons.
- If the structure of the file to be modified changes drastically, the parser script may fail
- (Static) changes made during a system upgrade may conflict with the 'old' changes the scripts are trying perform dynamically
- The parser/generator scripts may very well become quite lengthy, complex and difficult to read through
- The changes could be punctual, limited only to what differ when running stand-alone from when running from colinux.
We could also use a simple script that just calls 'patch' to apply some diffs, depending on the current running mode. But I think this would be less flexible (though simpler to do).
Implementing #IF, #ELSE, #ENDIF Edit
The majority of the Unix-like configuration files use the pound symbol, #, to mark a line as a comment. This allows us to implement a very simple pre-processor to convert configuration files between coLinux and normal Linux kernels. The following examples show how such a pre-processor can be applied to /etc/fstab:
LABEL=/ / ext3 defaults 1 1 /dev/hda8 swap swap defaults 0 0 #IF COLINUX 0 /mnt/d cofs defaults 0 0 #ELSE #&@/dev/hda5 /mnt/d ntfs ro,umask=0227,gid=disk 0 0 #ENDIF none /dev/pts devpts gid=5,mode=620 0 0 none /dev/shm tmpfs defaults 0 0 none /proc proc defaults 0 0 none /sys sysfs defaults 0 0
- normal lines will not be modified,
- lines in the disabled section are marked with the magic comment sequence #&@,
- lines in the enabled section that start with #&@ have these characters removed.
The magic comment sequence is an improbable sequence of characters to allow you to continue to use the normal comment character within the pre-processor sections should you need to disable lines or add real comments.
A simple pre-processor can be implemented in python as follows:
#!/usr/bin/python # # Mini-language to enable and disable colinux adaptations # import sys, getopt # named constants COMMENT_STATE = 0 UNCOMMENT_STATE = 1 UNTOUCHED_STATE = 2 def help_issue(full = False): print "Usage: colinux.py [OPTIONS] <filename> ..." if False != full: print """ Options: -h, --help Print help information, then exit. -c, --colinux Switch into coLinux mode (default is to switch off coLinux) """ else: print "(try --help)" def parse_args(args): # set up the defaults defaults class struct: pass opts = struct() opts.colinux = False try: flags, args = getopt.gnu_getopt(sys.argv[1:], "hc", ["help", "colinux"]) except: help_issue() return None for f, a in flags: if f in ("-h", "--help"): help_issue(True) return None elif f in ("-c", "--colinux"): opts.colinux = True return opts, args def select_and_print(l, a, b, c): print c if l: return a else: return b def main(): try: opts, args = parse_args(sys.argv) except TypeError: return 1 state = UNTOUCHED_STATE for i in sys.stdin: i = i.strip('\r\n') if i.startswith('#IF COLINUX'): state = select_and_print(opts.colinux, UNCOMMENT_STATE, COMMENT_STATE, i) elif i.startswith('#IF LINUX'): state = select_and_print(opts.colinux, COMMENT_STATE, UNCOMMENT_STATE, i) elif i.startswith('#ELSE'): assert(state != UNTOUCHED_STATE) state = select_and_print(state == COMMENT_STATE, UNCOMMENT_STATE, COMMENT_STATE, i) elif i.startswith('#ENDIF'): assert(state != UNTOUCHED_STATE) state = select_and_print(True, UNTOUCHED_STATE, 0, i) elif state == COMMENT_STATE: if i.startswith('#&@'): print i else: print '%s%s' % ('#&@', i) elif state == UNCOMMENT_STATE: if i.startswith('#&@'): print i[3:] else: print i else: print i return 0 if <u>name</u> == "<u>main</u>": try: sys.exit(main()) except KeyboardInterrupt: sys.exit(5)
The following shell script can be used to run the pre-processor against whatever files need to be modified:
#!/bin/sh COLINUX_PY=/root/colinux.py # find out which kernel we are running on if uname -r | grep -qe "-co-" then COLINUX_PY_ARGS=-c else COLINUX_PY_ARGS= fi for i in \ /etc/modprobe.conf \ /etc/fstab \ /etc/sysconfig/network-scripts/ifcfg-eth1 do cp $i $i.bak python $COLINUX_PY $COLINUX_PY_ARGS < $i.bak > $i done
Implementing Patch System Edit
How to apply the patch scenario. Create two copies of fstab, one fstab.normal, and one fstab.colinux. Then create two diff files for them. One to patch fstab.normal so as to be colinux mode, and the same for fstab.colinux, so that it changes to normal
<Brillgene:> Updating patch system to allow multiple boots into the same kernel (colinux/normal). Uses Unified patches as well as Error Redirection to make output clean. This will soon be available as a set of init scripts. Watch this space!
# diff -u fstab.normal fstab.colinux > colinux-fstab.patch
Now we have the patch file. We now create a script to patch fstab depending on the kernel running.
#!/bin/sh # find out which kernel we are running on, do the patch # we put the last working directory into a variable so we can cd back into it after OLDPWD=`pwd` cd /etc if uname -r | grep -qe "-co" then # Patch to colinux fstab patch fstab -s -f -r /tmp/patch.reject < colinux-fstab.patch > /dev/null else # Reverse patch to normal fstab patch fstab -s -f -R -r /tmp/patch.reject < colinux-fstab.patch > /dev/null fi # lets cd back into the last working directory cd $OLDPWD
Put this script in your init.d folder, I called it fix.coLinux.fstab. In your boot script (Under SuSE 9.3, it's /etc/init.d/boot, it may be the same for you). I placed a line to call the script right after the console/splash initialization. The rootfs must be mounted read write at booting time. This method works for me.
Skipping some scripts under coLinux boot Edit
You may also need to do the same thing for boot.clock, hwscan, kudzu, powerd and other power management daemons as well as any type of hardware scanning. This is needed only if coLinux crashes on startup, otherwise you may have some fun with coLinux with very little modification. Edit non-working scripts and add these lines in the top of script replacing sample with the service name:
#!/bin/sh # # One of the file /etc/init.d/sample # # +++ added to skiping these script under coLinux boot. if uname -r | grep -qe "-co-" then echo "sample skipped (Colinux)" exit 0 fi # # +++ continue with the default code of the script ...
See also Edit
MassTranslated on 25 Dec 2004.
Manually Adjusted on 25 Dec 2004. - had to remove some anchor and links.
Major rewrite by Eyal Rozenberg 04 Apr 2005 ; comments are welcome: firstname.lastname@example.org
MassTranslated on Sun Apr 23 17:36:03 UTC 2006