hprofile 2.0 ReadMe ------------------- READ THIS FILE BEFORE YOU DO ANYTHING STUPID (That is, read it, then go do something stupid). No, seriously. You may think you know all there is to know about everything there is anything to know anything about, but you don't know jack about hprofile until you've read the readme. Or put differently - these scripts have the potential to screw your system over in more than one way, and if you just randomly drop files in /etc/hprofile/files, alter a few boot scripts and think that's that, you're more than likely to lose a few pretty long and important configuration files. You have been warned! That said, this program works wonders for me, and there's no reason why it shouldn't for you. 0. The quick and dirty installation guide: Work from the examples! - Run the 'install' script as root to install the scripts and example configuration. - Run "hprofile -h" and "hprunlevel -h" to get an overview of their capabilities. - Have a look at the example configurations in /etc/hprofile. The thing to realise quickly is that a "profile type" is a grouping of profiles for a specific type of configuration (e.g. a 'power' profile type contains profiles like AC, Battery or Performance). Each profile type has a configuration directory in /etc/hprofile/profiles (and possibly in ~/.hprofile/profiles/) where it defines scripts to be run when profiles are applied or stopped, files to be substituted (for each file that varies between profiles, there is one version per profile, with an extension of ".", in a directory which mirrors its intended location in the file system), a list of which profiles are valid (optional), and a script called 'ptest' which should output the name of the currently valid profile (e.g. after examining some state of the system, or even asking the user). Read on for more detailed help. 1. Preface hprofile was written my Martin Aspeli , and is released under the GNU General Public License, version 2.0 (see the file COPYING). It comes with NO WARRANTY WHATSOEVER. It works great for me, but if it decides to delete all your files, blackmail your boss and run away with your mother-in-law, don't come crying to me! Bug report and suggestions for improvements are always welcome, however. 2. Usage The following sections describe how hprofile works and how to use it. 2.1. Overview hprofile is a system consisting of three scripts, hprofile, hpdet and hprunlevel. I wrote it so that I could use my installation of Gentoo Linux both in VMWare for Windows and for dual-booting. VMWare Workstation 3.0 comes with some of this support, but their "dualconf" system was not flexible enough for me. Theoretically, you can use hprofile for any system where you'll need different versions of core configuration files depending on the state your computer is in. One example apart from VMWare would be a laptop which may or may not be in a docking station. As of version 2, hprofile has grown to include more general support for profiles. You can now run arbitrary scripts before and after a profile is applied, and you can manage several types of profiles. The functionality offered by hprofile version 1 is catered for by the 'boot' profile. Other profiles can be defined to cater for different needs. For example, I use a 'net' profile to manage my wireless network settings. 2.2. Defining and applying profiles A "profile" is basically a collection of configuration files that need to be different depending on some external condition. Profiles are grouped into types. For example, you can have a 'boot' profile that sets files such as scripts in /etc/modules.d/ or /etc/X11/XF86Config depending on the state of your hardware at bootup. Separately, you can have a 'net' profile that controls the state of your network files, such as /etc/hosts or /etc/resolv.conf. Each profile type must have a unique name, as must each profile. The 'boot' profile called 'vmware' is referred to as 'boot.vmware' and is different from the profile 'boot.dualboot'. You could have a separate 'net' profile called 'net.vmware', too. To switch profiles, you can run "hprofile .", for example "hprofile boot.vmware". It is also possible to automatically determine the profile using the "hpdet" script. In this case, run "hprofile " only (e.g. "hprofile boot"). See the discussion on hpdet and ptest below. Lastly, the 'boot' profile is special in that it can be associated with a bootup runlevel. See the discssion on 'hprunlevel' below. To define a profile type, create a directory in /etc/hprofile/profiles. For example, /etc/hprofile/profiles/boot is used to hold the configuration files pertaining to the 'boot' profile. This directory should contain the following: - default -> A text file containing the name of the default profile of this type (and nothing else!). - files/ -> A directory mirroring the parts of the filesystem where profile-specific files are found (more below). - ptest -> An executable script used to determine the current profile. The script should output the name of the current profile (only), or output nothing if it is unable to determine the profile. In this case, the fallback profile specified in the file 'default' will be assumed. This is only relevant where hprofile or hprunlevel is called without a specific profile, only a profile type. Optional executable scripts: - pre-start -> A script which, if present, will be run before file switching takes place when the profile is applied. - post-start -> A script which, if present, will be run after file switching takes place when the profile is applied. - stop -> A script which, if present, will be run when the the current profile is replaced, or if you run 'hprofile -s '. - scripts/* -> This directory contains executable scripts, at most two for each profile, name .start and .stop. If present, these will be run when the profile is started (after configuration files have been switched) and stopped. Optional configuration files: - profiles -> A file listing all valid profiles of this type, one per line, (and nothing else!). If this file is present, it will constrain the profiles considered by hprofile (i.e. hprofile won't apply any profiles not listed in the profiles file); if not, hprofile will look through the files in the 'files' directory and check their extensions to find profile names, which is a lot less efficient and could produce false positives. The files/ directory is where the magic happens. This mirrors the file system with configuration files. Each file is suffixed with the profile name. Hence, the file /etc/hprofile/profiles/boot/files/etc/X11/XF86Config.vmware is the VMWare-specific version of /etc/X11/XF86Config. The corresponding XF86Config.dualboot is the dualboot version. If you run 'hprofile boot.vmware', a symbolic link will be created from /etc/X11/XF86Config to the file /etc/hprofile/profiles/boot/files/etc/X11/XF86Config.vmware. The original will be backed up to /etc/hprofile/profile/boot/files/etc/X11/XF86Config.bak if it did not come from any of the 'boot' profiles. Before this substitution takes place, the pre-start script found in /etc/hprofile/profiles//pre-start will be run, if it exists and is executable. After the substitution takes place, the post-start script in /etc/hprofile/profiles//post-start will be run, if it exists and is executable. In both cases, the name of the profile being switched too (e.g. 'vmware' or 'dualboot' in the 'boot' profile example above) is passed to the script as a command-line argument. The name of the current profile is then stored in a plain text file in /var/run/hprofile/. When a new profile is applied subsequently, the previous profile's stop script, found in /etc/hprofile/profiles//stop, is run, should it exist. This is passed the name of the current profile (before the new profile is applied), as found in the state file in /var/run/hprofile. You can also manually "stop" a profile by running "hprofile -s ". This is useful if you start some service from the post-start script, and wish to stop it in the stop script. The functionality described above is all system-wide. hprofile assumes it runs with root privileges, and pre-start, post-start and stop scripts are all run with root privileges. In addition to this, each user listed in /etc/passwd with a valid home directory, can create a ~/.hprofile/profiles/ directory. This directory can then contain a similar mirroring as that of /etc/hprofile/profiles//files, but of the user's home directory. Hence, if the user wants to use a different ~/.xscreensaver file, say, to avoid enabling OpenGL graphics-intensive screensavers in a VMWare session (VMWare does not have hardware-accelerated graphics), he can create the file ~/.hprofile/profiles/boot/files/.xscreensaver.dualboot for the 'dualboot' profile and ~/.hprofile/profiles/boot/files/.xscreensaver.vmware for the 'vmware' profile. For obvious security reasons, this will only work on files inside the user's home directory! Hence, if the user creates ~/.hprofile/profiles/boot/files/etc/passwd.vmware he will not be able to overwrite /etc/passwd (can't blame a boy for tryin' though, can you?), but if there is a ~/etc/passwd for that user, that will be replaced. (If you understand why that is, you've probably got a pretty good grasp on how hprofile works.) Users can also create pre-start, post-start or stop scripts for each profile type, but for security reasons, these have to run with the privileges of the user in question. To accomplish this, hprofile uses the 'sudo' tool, so make sure it is installed. The order of execution of events when a new profile is applied, is as follows: 1. Stop scripts for the current profile, presuming there is one 1.1. User-level scripts (for each user): 1.1.1. First, ~/.hprofile/profiles//stop 1.1.2. Then, ~/.hprofile/profiles//scripts/.stop 1.2. Global stop scripts 1.2.1. First, /etc/hprofile/profiles//stop 1.2.2. Then, /etc/hprofile/profiles//scrips/.stop 2. Pre-start scripts for the new profile 2.1. User-level: ~/.hprofile/profiles//pre-start 2.2. Global: /etc/hprofile/profiles//pre-start 3. Configuration files switched 4. Post-start scripts for the new profile 4.1. User-level: 4.1.1. First, ~/.hprofile/profiles//scripts/.start 4.1.2. Then, ~/.hprofile/profiles//post-start 4.2. Global: 4.2.1. First, /etc/hprofile/profiles//scripts/.start 4.2.2. Then, /etc/hprofile/profiles//post-start Naturally, if any scripts are missing, they are simply not executed. If any pre-start script returns an error (a non-zero exit code), processing of the profile (for the individual user only, if a user-level pre-start script fails) will be aborted. To turn user profiles off, set "userprofiles=0" in /etc/hprofile/conf. See that file for more configuration options. 2.3. Automatically determining the current profile The script 'hpdet' is used to automatically determine the correct profile of a given type at the present time. Call "hpdet " (e.g. "hpdet boot") to determine the profile. To determine the profile, hpdet will call the script 'ptest' in the profile type directory (e.g. /etc/hprofile/profiles/boot/ptest), which should print (only) the name of the currently valid profile to the standard output. One way that ptest could accomplish this would be to grep through the output of dmesg or examining /proc or /dev to assertain some state external to the system. Another way would be to look for options passed on the kernel command line (you can set this via the lilo append line, or as part of the "kernel" line if you're using grub), which you can access via /proc/cmdline. Alternatively, you could ask the user, or do anything else that makes sense. If 'ptest' does not output anything (i.e. it was unable to determine the profile), 'hpdet' will assume the file 'default' in the profile directory contains (only) the name of the default or "fall-back" profile. 2.5. hprunlevel - Selecting the startup runlevel based on the hardware profiles You'll probably want to associate different runlevels with your hardware profiles to start certain services only in some profiles (the vmware guest tools are a good example). To make this easier, put the names of a profiles, followed by some whitespace followed by a digit representing the runlevel, one on each line (and nothing else), in /etc/hprofile/runlevels. For example: dualboot 4 vmware 5 These profiles refer to the 'boot' profiles, found in /etc/hprofile/profiles/boot. Then use the 'hprunlevel' script, called with the profile as the first argument, which examines this file and echoes the runlevel, which can then be used to tell init to switch runlevels. Alternatively, 'hprunlevel' can use 'hpdet' as described above to find the currently valid 'boot' profile, presuming you've set up the 'boot' profile 'ptest' script sensibly. I've found that the best way of selecting a runlevel at startup, is to use the default runlevel (usually runlevel 3) as a dummy, that contains only one service, which prints a warning that something went wrong in runlevel selection. At the very end of the "boot" runlevel (the one that has all the scripts that get run once only, when the system is booted, before init enters the default runlevel), put a script (this means start its name with S99 in most distros, and set a dependency of "after *" in Gentoo Linux) that does something like the following: runlevel=$(/usr/local/sbin/hprunlevel) echo "Switching to runlevel ${runlevel}" /sbin/init ${runlevel} This will switch to the correct "real" runlevel. If you want to avoid that, you can try to use hprofile to switch some of the scripts in /etc/init.d around, using dummies for services you don't want for a given profile. In this case, it becomes very important to make sure hprofile runs before any "normal" bootup services, preferably right after filesystems have been mounted. Please note that this will require some trial an error. Two key points to keep in mind is that you can always go single-user to fix something that went wrong (do "linux s" on a LILO or GRUB command line), and do keep backups of your entire runlevels directory (/etc/rc.d on many systems; /etc/runlevels on Gentoo). 3. Installation The script install in the distribution directory will copy skeleton files to /etc/hprofile and copy the three scripts (hprofile, hpdet, hprunlevel) to /usr/local/sbin. Modify this script or perform the installation manually if you want them elsewhere. You'll then need to edit /etc/hprofile/profiles/boot/ptest to determine the current 'boot' profile and echo it (see above) and/or modify the LILO append line or GRUB menu to specify profiles (see above). If you want hprofile to run at bootup (you probably do), you'll need to put calls to /usr/local/sbin/hprofile (and possibly /usr/local/sbin/hprunlevel) in your startup scripts (on some systems, /etc/init.d/boot.local may be a good place), preferably right after local filesystems have been mounted. If you use hprunlevel, you'll need to also modify the file /etc/hprofile/runlevels, and make sure that the runlevels correspond to those in /etc/inittab and /etc/init.d/rc.d or /etc/rc.d or /etc/runlevels. Next, you'll have to place the profile-specific versions of any files you want used in /etc/hprofile/profiles//files, in directories mirroring their intended locations in the filesystem hierarchy. One likely example is /etc/modules.conf. Presuming you want vmware and dualboot as your profiles, copy /etc/modules.conf to both /etc/hprofile/etc/modules.conf.vmware and /etc/hprofile/etc/modules.conf.dualboot, and modify them to your liking. And MAKE A BACKUP OF THE ORIGINAL. Don't think you won't mess it up. You will. I promise! In fact, throughout this process - KEEP BACKUPS! You're bound to mess something up the first time! Also, test hprofile (after you've made backups!) before rebooting, as you may render your system unbootable. 4. The example configurations The following sections describe the example configurations and how they work. Note that the example configurations are found in the directory example-profiles, because otherwise you could risk accidently overwriting your configuration files with mine! However, versions of the example profiles without any configuration files in the 'files' directory are installed in the profiles directory by default, to give you some scripts and settings to base your own configuration on. 4.1. The 'boot' profiles - VMWare vs. dual boot The 'boot' profile, as mentioned above, is special in that it can be associated with a runlevel. The example boot profile here is based on my configuration, which distinguishes between the hardware emulated by VMWare and my real hardware. Some of the locations of these files may be specific to Gentoo Linux. The file /etc/modules.autoload.d/kernel-2.6 contains modules which will be loaded at startup. The file /etc/conf.d/net contains Gentoo network configuration. The file /etc/modules.d/alsa contains ALSA sound settings. This profile does not make use of any scripts, but it is loaded at startup. Look at the files in the extra/rc-scripts directory to see the Gentoo init scripts that load the profile. Note that Gentoo is quite different from RedHat-based systems when it comes to init scripts, so you may need to roll your own scripts - if you do, please email them to me (optilude@gmx.net), and I'll include them in the future. To gentoo users: The init scripts hprunlevel and hprofile exist in the boot runlevel, and I have two extra runlevels in /etc/runlevels called dualboot and vmware. These are set to runlevels 4 and 5 respectively in /etc/inittab, and contain all services for those two runlevels; the default runlevel is empty except for the hprunlevel-warning service. Also note that for hprofile to be run before the 'modules' service, you need to add a hidden file ".critical" in /etc/runlevels/boot. This file should contain the following line only: checkroot hostname hprofile modules checkfs localmount This is because recent versions of the gentoo boot scripts define some boot services as "critical", which are started first, regardless of other scripts' dependencies. hprofile needs to run before modules (presuming you want to change which modules are loaded at bootup using hprofile), so we need to define it as a "critical" service. 4.2. The 'net' profiles - Connecting to multiple networks This profile uses scripts and configuration files to connect to multiple networks. It's worth browsing through the start and stop scripts in the 'scripts' directory to see how they work. Again, some of this will be Gentoo specific, but it should be a useful starting point. The thing to notice here is that ptest outputs the current profile every time, which is based on the assumption that you'll want to keep using the same network profile until you manually switch it. To make this work properly across reboots, though, the rc script (found in extra/rc-scripts/gentoo/net.profile) actually starts the *previous* profile at boot. The reason is that at shutdown, the profile is stopped (to ensure the network is stopped properly), using "hprofile -s net". This in turn makes the "current" profile the "previous" one. Get it? :-) The net result is that the last profile you set is "remembered" the next time you boot. You could be even more clever, by making a net 'ptest' script which would select the network profile by probing the network (e.g. by trying to get a DHCP address and seeing which subnet it's on). As always, example setups are more than welcome to optilude@gmx.net. 4.3. The 'power' profiles - Saving battery life This profile uses only scripts in the 'scripts' directory, and does not switch any configuration files. It uses the "speedfreq" command to change the CPU speed (I have an Intel Pentium-M/Centrino chip, but speedfreq should be able to scale down other types of CPU as well), and ASUS-specific ACPI extensions to change the brightness of the display. Unless you have a Centrino based ASUS-made laptop, you probably have to change these if you want to use them, but it should be fairly straightforward. I have seen reports of others using xgamma to change the brightness, but this never worked for me. If you have a working set of power profile scripts, please email them to me (optilude@gmx.net), and I'll include them in the distribution in the future. 5. Limitations There is no way to specify that a given file should not be present in a given profile. If a given file exists in one profile but not another, hprofile will simply leave whatever is there when switching to the profile that doesn't have the file. The procedure to find out which users in /etc/passwd are actually valid users (that is, real people who can log in, and not just daemon users) is somewhat unelegant, and requires access to /etc/shadow (it only reads this file once to find out which users have non-* password fields, but still), which you may or may not appreciate. Suggestions for a better way to list all real users on the system would be appreciated. If you can come up with other features you want added to (or bugs removed from) hprofile, please drop me a line (or a patch) at optilude@gmx.net. 6. Extras Some extra scripts can be found in the 'extra' directory (these are not installed by default). At present, this includes: - Init scripts for Gentoo Linux to load the 'boot' profile and select the boot profile runlevel. - A script called 'select-profile' which lets you graphically select a profile of a given type by running 'select-profile '. This uses zenity, part of Gnome, to display a menu. - An example /etc/acpi directory which defines ACPI rules and scripts to change the power profile automatically when the AC adapter is plugged in or pulled out. 7. Warning I've tested this with the example profiles on Gentoo Linux on my laptop. I haven't had any problems with it, and it works great for me, but consider yourself a field tester if you try to use it! 8. Contact If you need more help or have suggestions or bug reports, please don't hesitate to contact me at optilude@gmx.net.