On Sun, Apr 7, 2013 at 10:21 PM, John Lane <[email protected]> wrote: > I have been trying to replace an rc script with a systemd unit file. It is > for an rvm (ruby version manager) environment and it starts a documentation > web server. I tried to create a service unit thus: > > [Service] > Type=forking > User=rvm > ExecStartPre=/bin/bash --login /etc/profile.d/rvm.sh > ExecStartPre=/usr/local/rvm/bin/rvm use %i > ExecStart=/${GEM_HOME}/bin/gem server --daemon --port 8808 > > The rvm environment needs to be initialised (by running > /etc/profile.d/rvm.sh) and this needs to happen in a bash login shell (this > is due to the design of rvm). > > I think the ExecStart* lines in the above example are each invoked in a > separate environment (so the initialisation performed by the first is lost > before the second and third items are processed). Is this right or do I > misunderstand?
That's right, but not because of systemd. When you run "bash /etc/profile.d/rvm.sh", it works in non-interactive mode: first it interprets the given script, then simply exits. This is the same regardless of where and how it is run. Since profile.d/rvm.sh just sets environment variables, and those do not propagate upwards, the entire command has no effect. In actual login sessions, your shell starts and "sources" /etc/profile, which then "sources" the profile.d scriptlets – instead of running a separate copy of bash for them. Since systemd is not a shell and does not understand (ba)sh syntax, the same thing cannot be done here, at least not directly. > My question is to ask how would I create a unit that starts a service in an > properly initialised environment when the only way to initialise that > environment is to run a bash setup script that requires it to be run in a > login shell ? My first thought is "fix the damn setup script". Surely rvm already has a way to be used non-interactively?... Actually – is the "login shell" requirement imposed by rvm.sh itself checking for that, or simply by the fact that rvm.sh is in /etc/profile.d? — If it's the former, then rvm is broken, but if it's the latter, then it's not a real requirement as rvm.sh could be sourced manually without relying on /etc/profile to do it. It might be that all you need is to set $PATH and $GEM_HOME environment variables using the Environment= property (or EnvironmentFile=.) (But note that you cannot use variables in the zeroth argument for ExecStart.) > My solution that works is to use a unit to invoke a bash script that > performs the initialisation and then starts the service. But I feel this > somewhat negates the benefits of systemd not being based on shell scripts. > I'd like to try and get it to work with a unit file and no supporting > scripts, if this is possible. It doesn't completely negate the benefits, as the script only performs initialization for your service – you still get the advantages of systemd enforcing dependencies, starting multiple services in parallel, process tracking, and pretty much everything else. The only significant downsides I can think of are having to load heavy /bin/bash, and similarly heavy rvm. I use rbenv to manage different Ruby versions, and while it probably doesn't offer the same functionality as rvm, it's also much simpler to use: it only needs <rbenv-path>/shims to be added to $PATH. -- Mantas Mikulėnas <[email protected]> _______________________________________________ systemd-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/systemd-devel
