Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

This may have more to do with detecting operating systems, but I specifically need the init system currently in use on the system.

Fedora 15 now uses systemd, Ubuntu uses Upstart, while others use variations of System V.

I have an application that I am writing to be a cross-platform daemon. The init scripts are being dynamically generated based on parameters that can be passed in on configure.

What I'd like to do is only generate the script for the particular init system that they are using. This way the install script can be run reasonably without parameters as root and the daemon can be "installed" automagically.

This is what I've come up with:

  • Search for systemd, upstart, etc in /bin
  • Compare /proc/1/comm to the systemd, upstart, etc
  • Ask the user

What would be the best cross/platform way of doing this?

Kind of related, Can I depend on bash to be on the majority of *nix or is it distribution/OS dependent?

Target platforms:

  • Mac OS
  • Linux (all distributions)
  • BSD (all versions)
  • Solaris, Minix, and other *nix
share|improve this question
1  
Just to add my two cents, bash isn't installed by default on FreeBSD. –  Chinmay Kanchi Aug 7 '11 at 3:27
    
@tjameson, did you find a more direct way? I'm looking for the same thing but the answers here are just directions, not direct answers. In particular 1) script locations to search and 2) detecting the init system in effect, in case there are multiple ones installed (bash was answered directly). –  naxa Nov 24 '13 at 11:13
1  
@naxa - Short answer, no. Long answer, you can get pretty far with ps -p 1 -o command (prints the path to the current init). On Arch Linux and Fedora (IIRC), it's a symlink to the systemd binary (probably same on all systemd systems). On upstart, init --help will print usage information, and on my box, upstart is mentioned where it says who to email. On FreeBSD (sysV), this will return an error. There may be similar clues on other systems, but since asking this question, I've decided to just create them for all platforms and make separate packages for each one. –  tjameson Nov 24 '13 at 19:48
    
thanks great info! Hopping from that I've learned that sudo lsof -a -p 1 -d txt may give even more exact results. ps may print an arbitrary name, whereas with lsof you will get the real executable path. (See my question unix.stackexchange.com/questions/102453/… ) –  naxa Nov 24 '13 at 22:25
1  
None of the answers or comments in the linked question are bash related. The solutions should be applicable to your case as well. –  Marco Feb 10 at 20:20
show 3 more comments

4 Answers

up vote 6 down vote accepted

For the second question, the answer is no and you should have a look at Resources for portable shell programming.

As for the first part - first of all, you certainly have to be careful. I'd say perform several tests to make sure - because the fact that someone does have systemd (for ex.) installed, does not mean it is actually used as the default init. Also, looking at /proc/1/comm can be misleading, because some installations of various init programs can automatically make /sbin/init a symlink hardlink or even a renamed version of their main program.

Maybe the most useful thing could be to look at the init scripts type - because those are what you'll actually be creating, no matter what runs them.

As a side note, you might also have a look at OpenRC which aims to provide a structure of init scripts that is compatible with both Linux and BSD systems.

share|improve this answer
1  
What do you mean by "look at the init scripts type"? Often different init systems put their scripts/files somewhere besides /etc/init, like systemd puts them in /etc/systemd. If I was to have my script grok these, it could take a little while. Oh, and thanks for the link BTW for portable shell programming. –  tjameson Aug 7 '11 at 0:23
1  
I meant to say that some init implementations can be adjusted to make use of different init scripts' types and locations (like /etc/rc.d/ or /etc/init.d/). And you should properly adjust your program at installation time to utilize the structure that is used on the given system. –  rozcietrzewiacz Aug 7 '11 at 1:08
1  
So, are you saying that there is no reliable way to detect the init system programmatically? Having the user pass in parameters is certainly safer, but if the user does not pass anything in, what would be the best way to guess? –  tjameson Aug 7 '11 at 1:27
    
I've no idea what will be the best way for your program - it all depends on what systems will the program end up running. I haven't used too many distributions, but I was trying to share my observations to help you. It is a tough piece of scripting you are about to try and I tried to give you some view on the field - you must come to the final answer yourself or wait for more hints. –  rozcietrzewiacz Aug 7 '11 at 1:40
    
Cool, thanks for all your help. You definitely have pointed me in the right direction. –  tjameson Aug 7 '11 at 1:47
add comment

Using processes

Looking at the output from a couple of ps commands that can detect the various versions of systemd & upstart could be crafted like so:

upstart

$ ps -eaf|grep [u]pstart
root       492     1  0 Jan02 ?        00:00:00 upstart-udev-bridge --daemon
root      1027     1  0 Jan02 ?        00:00:00 upstart-socket-bridge --daemon

systemd

$ ps -eaf|grep [s]ystemd
root         1     0  0 07:27 ?        00:00:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 20
root       343     1  0 07:28 ?        00:00:03 /usr/lib/systemd/systemd-journald
root       367     1  0 07:28 ?        00:00:00 /usr/lib/systemd/systemd-udevd
root       607     1  0 07:28 ?        00:00:00 /usr/lib/systemd/systemd-logind
dbus       615     1  0 07:28 ?        00:00:13 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation

Paying attention to what the name of the process is that's PID #1 can also shed potential light on which init system is being used. On Fedora 19 (which uses systemd, for example:

UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 07:27 ?        00:00:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 20

Notice it isn't init. On Ubuntu with Upstart it's still /sbin/init.

$ ps -efa|grep init
root         1     0  0 Jan02 ?        00:00:03 /sbin/init

NOTE: But use this with a bit of caution. There isn't anything set in stone that says a particular init system being used on a given distro has to have systemd as the PID #1.

The filesystem

If you interrogate the init executable you can get some info from it as well. Simply parsing the --version output. For example:

upstart

$ sudo /sbin/init --version
init (upstart 1.5)
Copyright (C) 2012 Scott James Remnant, Canonical Ltd.

This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.

systemd

$ type init
init is /usr/sbin/init

NOTE: The fact that init is not in its standard location is a bit of a hint/tell. It's always located on sysvinit systems in /sbin/init.

sysvinit

$ type init
init is /sbin/init

Also this:

$ sudo init --version
init: invalid option -- -
Usage: init 0123456SsQqAaBbCcUu

Conclusions

So there doesn't appear to be anyone way to do it but you could formulate a suite of checks that would pinpoint which init system you're using with a fairly high degree of confidence.

share|improve this answer
    
How about: pgrep systemd >/dev/null && echo init system: systemd –  Marco Feb 10 at 20:27
    
Thank you, this is exactly what I was looking for: some steps to take to try to determine the init system. –  cpburnz Feb 10 at 20:30
1  
The PID #1 doesn't necessarily be /usr/lib/systemd/systemd if systemd is used, it's a false assumption. On my system, for instance, PID #1 is /sbin/init (I use systemd). It is distribution dependent. –  Marco Feb 10 at 20:32
    
@Marco - OK, thanks I'll take that out. –  slm Feb 10 at 20:40
add comment
  1. This is what distro-specific packages are for. There is much more to installing software properly than just detecting the init system. Many distros use SysVinit but not all of them write their init scripts the same way. The proper way to solve this is to include all the different variants and then bundle it up using spec files with distro-specific dependency names for rpm distros, deb files for apt based systems, etc. Almost all distros have some sort of package specification you can write that includes dependencies, scripts, init scripts, etc. Don't re-invent the wheel here.

  2. No. Which brings us back to 1. If you need bash it should be a dependency. You can specify this check as part of your configure scripts, but it should also be in the package descriptions.

Edit: Use flags on your configure script such as --with upstart or --without sysvinit. Pick a sane default, then the scripts that package your software for other distros can choose to run this with other options.

share|improve this answer
    
Hmph, so it's looking like I can't have a 'one script to rule them all' solution. I've seen a lot of programs that use autoconf or similar to handle cross-platform stuff, but it doesn't seem like it's the right tool for my application. Is maintaining versions for each platform really the only reliable solution? –  tjameson Aug 7 '11 at 7:27
    
One installation script to rule them all is a BadIdea. It ends up failing more places than it works. Autoconf is good as far as it goes. Work hard on keeping your end of the software as generic as possible and include alternate init scripts in your package. Setup package specifications for several major distros. If your software is good you can get other people to help you out with getting it packaged for other systems. –  Caleb Aug 7 '11 at 7:34
    
@tjameson: I just realized I forgot the most important bit. This sort of thing is usually done with switches passed to the configure script. Each distro's build/package routines can call different switches, and your configure/make only has to know what switch it was passed, not detect all the possible software configurations. –  Caleb Aug 7 '11 at 7:38
    
@Caleb- Yeah, I already have that logic in there, but good catch. I was hoping for a way to sniff the init system to use an intelligent guess than a sane default. –  tjameson Aug 7 '11 at 7:40
add comment

On Gentoo, take a look at pid 1:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   4216   340 ?        Ss    2013   0:57 init [3]

If it is init, then the init system is OpenRC. If it is systemd, then the init system is systemd.

You can detect Gentoo with [ -f /etc/gentoo-release ].

Another method on Gentoo is to use profile-config show, which will show what default profile is in use. All of the profiles except the two ending in /systemd use the OpenRC init. Keep in mind, these are only representative of a default and it is possible that the user has taken steps to override that default and may not be indicative of the init manger actually in use.

share|improve this answer
    
Dumb question, but how do I check for pid 1? –  Faheem Mitha Feb 28 at 23:20
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.