early boot hook in launchd/launchctl?
Until recently, it was possible to put arbitrary code into /etc/ rc.server to perform scripted maintenance activities in the early boot context (i.e., system disk still write-only, limited driver access, etc). In the version distributed with 10.5.7, rc.server shows up later in the sequence (i.e., system disk mounted read-write). In any case, adding code to rc.server always was a kludge. Now, the cleanest way to do it seems to be to put code into /.env and use "nvram boot-args=-s ; reboot" to run it. This is actually a much cooler kludge, because /.env (the value of ENV in single-user mode) is normally run only in single-user mode, because otherwise the HOME variable will be set, and for root that will cause ENV normally to be defined as /var/root/.env. Because /.env only gets run in single-user mode, you can put in fairly elaborate checks to make sure you're in in the right place without negatively impacting startup time for normal root shell scripts. But I'm concerned that this method, like rc.server, will someday be seen by the launchd developers as a bug (that is, HOME not being defined in single-user mode); in this case, it too will suddenly disappear and some other kludge will have to be found. So what I'm wondering is whether it might not be a good idea to provide a conventional hook for early-boot maintenance. It could simply be a shell script in a standard location such as /etc/ rc.earlyboot which gets executed by launchd if present, owned by root, and not writable except by root. This would keep people who insist on doing this kind of thing from having to keep finding new and better kludges. Or, of course, the /.env thing and the HOME-less single-user shell could become a feature of launchd that is reserved for this purpose. Thank you, Greg Shenaut
On Jun 23, 2009, at 6:20 PM, Greg Shenaut wrote:
Until recently, it was possible to put arbitrary code into /etc/ rc.server to perform scripted maintenance activities in the early boot context (i.e., system disk still write-only, limited driver access, etc). In the version distributed with 10.5.7, rc.server shows up later in the sequence (i.e., system disk mounted read- write). In any case, adding code to rc.server always was a kludge.
What exactly are you doing that requires a read-only filesystem (I assume that's what you meant). What do you mean by "limited driver access"? Single-user mode doesn't stop the kernel from loading kexts as needed.
Now, the cleanest way to do it seems to be to put code into /.env and use "nvram boot-args=-s ; reboot" to run it. This is actually a much cooler kludge, because /.env (the value of ENV in single-user mode) is normally run only in single-user mode, because otherwise the HOME variable will be set, and for root that will cause ENV normally to be defined as /var/root/.env. Because /.env only gets run in single-user mode, you can put in fairly elaborate checks to make sure you're in in the right place without negatively impacting startup time for normal root shell scripts.
But I'm concerned that this method, like rc.server, will someday be seen by the launchd developers as a bug (that is, HOME not being defined in single-user mode); in this case, it too will suddenly disappear and some other kludge will have to be found.
.env is a feature of the shell, not launchd. Though it's not mentioned in bash(1). Perhaps you're referring to /etc/profile? If that's the case, I suppose we could someday invoke the shell with --noprofile or something in the future, but I don't see a compelling reason to do that. Also, we don't set ENV when invoking the shell for single-user mode. Also, the existence of rc.server is considered to be more of a necessary evil than a bug. :)
So what I'm wondering is whether it might not be a good idea to provide a conventional hook for early-boot maintenance. It could simply be a shell script in a standard location such as /etc/ rc.earlyboot which gets executed by launchd if present, owned by root, and not writable except by root. This would keep people who insist on doing this kind of thing from having to keep finding new and better kludges.
Or, of course, the /.env thing and the HOME-less single-user shell could become a feature of launchd that is reserved for this purpose.
This might come in the future, but not in the form you're expecting. -- Damien Sorresso BSD Engineering Apple Inc.
On Jun 23, 2009, at 9:08 PM, Damien Sorresso wrote:
On Jun 23, 2009, at 6:20 PM, Greg Shenaut wrote:
Until recently, it was possible to put arbitrary code into /etc/ rc.server to perform scripted maintenance activities in the early boot context (i.e., system disk still write-only, limited driver access, etc). In the version distributed with 10.5.7, rc.server shows up later in the sequence (i.e., system disk mounted read- write). In any case, adding code to rc.server always was a kludge.
What exactly are you doing that requires a read-only filesystem (I assume that's what you meant). What do you mean by "limited driver access"? Single-user mode doesn't stop the kernel from loading kexts as needed.
I clone the system disk to a firewire drive using hdiutil -srcdevice.
Now, the cleanest way to do it seems to be to put code into /.env and use "nvram boot-args=-s ; reboot" to run it. This is actually a much cooler kludge, because /.env (the value of ENV in single-user mode) is normally run only in single-user mode, because otherwise the HOME variable will be set, and for root that will cause ENV normally to be defined as /var/root/.env. Because /.env only gets run in single-user mode, you can put in fairly elaborate checks to make sure you're in in the right place without negatively impacting startup time for normal root shell scripts.
But I'm concerned that this method, like rc.server, will someday be seen by the launchd developers as a bug (that is, HOME not being defined in single-user mode); in this case, it too will suddenly disappear and some other kludge will have to be found.
.env is a feature of the shell, not launchd. Though it's not mentioned in bash(1). Perhaps you're referring to /etc/profile? If that's the case, I suppose we could someday invoke the shell with -- noprofile or something in the future, but I don't see a compelling reason to do that. Also, we don't set ENV when invoking the shell for single-user mode.
I think bash(1) is slightly inaccurate in its discussion of ENV. From observation, it appears that ENV is always defined (as $HOME/.env), but it will be sourced only if the file exists. Root's home directory is /var/root, so HOME would normally be defined as that, but in single- user mode, at least currently, HOME is not defined. For shells run by root, ENV would normally be /var/root/.env, but since HOME is undefined in single-user mode, it comes out as /.env. In any case, it sounds like from the launchd point of view, this method (which depends on HOME not getting defined in single-user mode) appears reasonably stable, which suits me OK.
Also, the existence of rc.server is considered to be more of a necessary evil than a bug. :)
Gotcha.
So what I'm wondering is whether it might not be a good idea to provide a conventional hook for early-boot maintenance. It could simply be a shell script in a standard location such as /etc/ rc.earlyboot which gets executed by launchd if present, owned by root, and not writable except by root. This would keep people who insist on doing this kind of thing from having to keep finding new and better kludges.
Or, of course, the /.env thing and the HOME-less single-user shell could become a feature of launchd that is reserved for this purpose.
This might come in the future, but not in the form you're expecting.
I'm sure that's true. Thanks, Greg Shenaut
-- Damien Sorresso BSD Engineering Apple Inc.
participants (2)
-
Damien Sorresso
-
Greg Shenaut