It appears that openrc may have broken "who -b". I believe that the init files are supposed to update /var/run/utmpx or more likely /var/run/utmp (since those are the files that "who -b" attempts to open) and the init process no longer does this.
Steps to Reproduce:
1. "who -b" to see what the old boot date was.
2. Reboot Linux
3. "who -b" to see if boot time has been updated.
On my system "who -b" says Dec 30 yet I know it was booted in March (/var/log/dmesg is dated Mar 14).
Init files should update /var/run/utmp with the correct boot date record.
$ who -b
system boot 2009-04-10 09:08
Works properly for me.
(In reply to comment #1)
> $ who -b
> system boot 2009-04-10 09:08
> Works properly for me.
Are you using baselayout-2? It works fine on my stable amd64 computer too, but on my ~amd64 I get the same problem as the reporter of the bug.
emerge --info for the affected system
Portage 2.2_rc28 (default/linux/amd64/2008.0/desktop, gcc-4.3.3, glibc-2.9_p20081201-r2, 2.6.29-gentoo-r1 x86_64)
System uname: Linux-2.6.29-gentoo-r1-x86_64-AMD_Phenom-tm-_9350e_Quad-Core_Processor-with-gentoo-2.0.0
Timestamp of tree: Fri, 10 Apr 2009 19:00:01 +0000
ccache version 2.4 [enabled]
dev-lang/python: 2.5.4-r2, 2.6.1-r1
sys-devel/autoconf: 2.13, 2.63-r1
sys-devel/automake: 1.5, 1.6.3, 1.7.9-r1, 1.8.5-r3, 1.9.6-r2, 1.10.2
CFLAGS="-march=native -ggdb -O2 -pipe"
CONFIG_PROTECT="/etc /usr/kde/3.5/env /usr/kde/3.5/share/config /usr/kde/3.5/shutdown /usr/share/config"
CONFIG_PROTECT_MASK="/etc/ca-certificates.conf /etc/env.d /etc/env.d/java/ /etc/fonts/fonts.conf /etc/gconf /etc/gentoo-release /etc/php/apache2-php5/ext-active/ /etc/php/cgi-php5/ext-active/ /etc/php/cli-php5/ext-active/ /etc/revdep-rebuild /etc/sandbox.d /etc/splash /etc/terminfo /etc/texmf/language.dat.d /etc/texmf/language.def.d /etc/texmf/updmap.d /etc/texmf/web2c /etc/udev/rules.d"
CXXFLAGS="-march=native -ggdb -O2 -pipe"
FEATURES="buildpkg ccache collision-protect distlocks fixpackages parallel-fetch preserve-libs preserved-rebuild protect-owned sandbox sfperms splitdebug strict unmerge-orphans userfetch userpriv usersandbox"
GENTOO_MIRRORS="http://mirrors.evolva.ro/gentoo http://ftp.roedu.net/pub/mirrors/gentoo.org http://mirrors.xservers.ro/gentoo http://distfiles.gentoo.org"
LINGUAS="ro en eo"
PORTAGE_RSYNC_OPTS="--recursive --links --safe-links --perms --times --compress --force --whole-file --delete --stats --timeout=180 --exclude=/distfiles --exclude=/local --exclude=/packages"
Unset: CPPFLAGS, CTARGET, FFLAGS, INSTALL_MASK, PORTAGE_COMPRESS, PORTAGE_COMPRESS_FLAGS, PORTAGE_RSYNC_EXTRA_OPTS
`who -b` does not work on my unstable amd64 or my stable x86 (but both run baselayout 2 and openrc) ... and ive rebooted them a couple times today ;)
it does work on my stable amd64 which is running baselayout 1
who -b fails on my amd64
however, utmpdump /var/run/utmp shows this
Utmp dump of /var/run/utmp
  [rc ] [ ] [ ] [ ] [0.0.0.0 ] [Sun Apr 12 11:57:01 2009 BST]
  [~~ ] [runlevel] [~ ] [ ] [0.0.0.0 ] [Sun Apr 12 11:57:01 2009 BST]
  [l3 ] [ ] [ ] [ ] [0.0.0.0 ] [Sun Apr 12 11:57:05 2009 BST]
  [c1 ] [LOGIN ] [tty1 ] [ ] [0.0.0.0 ] [Sun Apr 12 11:57:05 2009 BST]
Can someone do utmpdump /var/run/utmp on a working system?
I'm pretty sure that any error lies in sysvinit and not OpenRC
(In reply to comment #6)
> who -b fails on my amd64
> however, utmpdump /var/run/utmp shows this
> Utmp dump of /var/run/utmp
>   [rc ] [ ] [ ] [ ] [0.0.0.0
> ] [Sun Apr 12 11:57:01 2009 BST]
>   [~~ ] [runlevel] [~ ] [ ] [0.0.0.0
> ] [Sun Apr 12 11:57:01 2009 BST]
>   [l3 ] [ ] [ ] [ ] [0.0.0.0
> ] [Sun Apr 12 11:57:05 2009 BST]
>   [c1 ] [LOGIN ] [tty1 ] [ ] [0.0.0.0
> ] [Sun Apr 12 11:57:05 2009 BST]
> Can someone do utmpdump /var/run/utmp on a working system?
> I'm pretty sure that any error lies in sysvinit and not OpenRC
utmpdump on a working host:
$ utmpdump /var/run/utmp
Utmp dump of /var/run/utmp
  [si ] [ ] [ ] [ ] [0.0.0.0 ] [Thu Apr 09 18:19:24 2009 CDT]
  [~~ ] [reboot ] [~ ] [ ] [0.0.0.0 ] [Thu Apr 09 18:19:24 2009 CDT]
  [rc ] [ ] [ ] [ ] [0.0.0.0 ] [Thu Apr 09 18:19:31 2009 CDT]
  [~~ ] [runlevel] [~ ] [ ] [0.0.0.0 ] [Thu Apr 09 18:19:31 2009 CDT]
<snip after the time that 'who -b' outputs>
$ who -b
system boot Apr 9 18:19
If /var/run/utmp is removed and the system is rebooted the who -b works correctly for the next boot only. I am at a loss to explain why this is so.
Roy, what kind of system are you running -- one with mountable system partitions (i.e. /root, /usr, /var & /tmp all on separate devices) or one with a "unified" system file system (all "system" directories on a single partition)?
I run mountable system partitions and ran into problems during the openrc changeover (a nightmare in my case because I just assumed the openrc upgrade was like any other "user-package" upgrade, didn't bother to back the root up, had to deal with backing out init/conf files from old root backups, etc.) Gentoo should *really* warn about upgrades that can *really* break the system boot process.
At any rate, in the process I ran into a number of cases where the system was trying to do things which required /usr (e.g. gnustep (/usr/GNUstep/System), X11 (/usr/lib), etc.) or /var (all the daemon managed programs, syslogd, and whomever (?!?) sets the boot time into /var/run/utmp. When those file systems were not mounted (for whatever reasons) the init scripts tended to break in very strange ways. This only showed up when I booted single user and found that a normal boot was mounting /usr and /var on "partially" built trees. Apparently some init processes will create directories and files that don't exist and some will not. I don't recall exactly how I ran into this situation but it pointed out that the entire init process needs to be tested completely on both unified and mountable system partitions (trees).
My current bootmisc seems to want a writeable /var/run and seems bypass playing with /var/run/utmp if it doesn't exist. So the sequencing of bootmisc and file system mounting or failures to mount (esp. /var) could be involved.
I seem to have missed this comment - my appologies.
My laptop has a setup of LVM + many volumes, all mounted correctly.
From memory it's like so
And I've not had many problems over the years, even with development code.
I am running OpenRC and see the same problem. The boot entry in /var/run/utmp is not being created. One more strange thing: the entry in /var/run/wtmp IS created. Also, I see the same behavior that Roy described: deleting /var/run/utmp BEFORE shutdown correctly creates the boot utmp entry on next boot.
I looked briefly at the sysvinit code: init checks to see if it can write to utmp by making a call to access(2), whereas wtmp calls open(2). However that may all be a worthless train of thought -- I'm just becoming familiar with init and OpenRC.
The question is precisely *when* during the init sequence is it calling the access/open calls? On my system /var is a mounted file system, so /var/run isn't going to exist if the access/open calls are used *before* /var is successfully mounted. I suppose the trick would be to create a /var/run on the root drive, then see if booting single user create the proper files. If so, then the proper solution might be to have the init.d mount script check to see if the files exist and do something like save them in /tmp, mount /var, then move them to their final location.
Ideally, init should not attempt to create these files until *after* any mounts of /var or /var/run are completed. Its a very tricky business when final file locations are on mounted file systems. I hate to see what would happen if somebody was using mounted file systems with /sbin or /etc.
I think that starting in single user mode should not work, because that would not load the boot level init scripts, and the "root" script that mounts /var/run as rw is in the boot runlevel in OpenRC.
I tested with single user mode anyway though, just in case I had missed something. I see the same failure.
Ok, I think I found it. The code in init is a little convoluted because it
seems to try and take into account that /var may not be mounted. But since
But if I check rc.log it looks like the mounts (/etc/init.d/localmount) are
done before bootmisc (which creates the utmp/wtmp files in /var/run). So it
"should work", unfortunately the code which is cleaning up /var/run (around
lines 91-106 in my version) only excludes utmp (and a few other files) from being deleted from /var/run. Since the just created wtmp is deleted init can't open it later on when it wants to write the boot record.
The easiest way to fix it is to simply add wtmp to the list of "allowed" files
in /var/run (in the "find /var/run ..." command). Tricky to find but easy to fix.
So this is actually a openrc bug (unless bootmisc is part of the sysvinit
package). I haven't verified this will work but it looks like it should.
Nice idea, but wtmp lives in /var/log and not /var/run
Sorry, I was not looking closely. Scratch the easy fix. Here is what I know so far.
1) It looks like the logic in init may be correct and it is compiled correctly.
2) /var/log/wtmp does contain the correct "reboot" record that init writes.
3) /var/run/utmp does not contain the correct "reboot" record that init writes at the same time it writes the wtmp record.
4) Writing records into utmp actually uses the function "pututline()" which is documented ("man pututline" works but the function isn't documented well if at all).
5) Looking at the glibc source code its clear that the pututline() function is designed to perform "locked" atomic writes to the utmp file (which makes sense since multiple logins/logouts could be occurring at the same time and they could overwrite each other's records).
6) I straced "who -b" and it is looking at utmp (if it looked at wtmp it would probably work).
7) The initial contents of utmp, as dumped by by the utmpdump program seems strange in that it contains the string "rc" but it isn't really in the correct location in the record. Now the "/sbin/rc" program is part of openrc package, not part of the sysvinit package.
Which would suggest that /sbin/rc is playing fast and loose with utmp, either not realizing that there should be a "reboot" record there, or not using the pututline() function (and writing to the file directly). I'll move onto openrc next, but the above would suggest that sysvinit and openrc *have* to be kept in sync with each other (and maybe glibc as well). If someone changes the structure of utmp (utmp.h which is part of glibc) probably both sysvinit and openrc are going to need to be recompiled.
And just to make this even more fun, "who" is part of the coreutils package, probably meaning that if utmp.h were to change then the coreutils package would need to be rebuilt as well. :-)
Now I think I've really got it and it wasn't easy. It seems to be a consequence of how inittab, init, and the openrc localmount & bootmisc scripts collectively operate.
1) init starts out with wrote_utmp_reboot = 1 (which would be valid in cases where one is doing a resume);
2) init also creates and closes UTMP_FILE (init.c:2443)
3) init starts with state 'si'/'#' (Notation here is inittab/init.) then goes into the SYSINIT -> BOOT transition -- the 'rc'/'*' this code (init.c:2197-2200) resets wrote_utmp_reboot = 0 and tries to write the BOOT_TIME record (presumably works for both utmp & wtmp) *if* /var is mounted;
3) init starts to run /sbin/rc boot which creates a fork to run all of the scripts in /etc/init.d, presumably executing localmount (mounting /var) and bootmisc (which clears utmp but leaves wtmp);
4) the "boot" sequence finishes up and comes back to init which goes off to deal with whatever needs to be done for the 'id' (initdefault) state -- but;
5) the code in utmp.c:write_utmp:127-141 which is supposed to catch cases where the BOOT_TIME record wasn't written will not work because its aleady bumped wrote_utmp_reboot.
I think the solutions perhaps involve:
1) Don't have bootmisc clear utmp (since init creates it); and/or
2) Move the line "if( type == BOOT_TIME) wrote_utmp_reboot++;" after the lines which try to fudge the BOOT_TIME record in utmp for cases when /var wasn't mounted.
A third possibility is a "delayed" creation of utmp by init if the first creation failed because /var wasn't mounted. I'm fairly sure bootmisc should not be playing with utmp/wtmp at all since init/agetty/login are the primary players with the files.
So the problem involves both the sysvinit and openrc packages. The util-linux package appears to behave properly with regard to using pututline() and related functions.
Interestingly, the "last" command will properly provide the system boot time and the uptime though not in as nice a format as "who -b" -- a consequence of the fact that it gets the information from wtmp rather than utmp.
I'm not sure, but it might be better for openrc to zero (not remove) /var/run/utmp during a shutdown (just before the localmount unmounts occur).