Search code examples
environment-variablesupstart

How to set environment variable in pre-start in Upstart script?


We have a custom C++ daemon application that forks once. So we've been doing this in our Upstart script on Ubuntu 12.04 and it works perfectly:

expect fork
exec /path/to/the/app

However now we need to pass in an argument to our app which contains the number of CPUs on the machine on which it runs:

cat /proc/cpuinfo | grep processor | wc -l

Our first attempt was this:

expect fork
exec /path/to/the/app -t `cat /proc/cpuinfo | grep processor | wc -l`

While that starts our app with the correct -t value, Upstart tracks the wrong pid value, I'm assuming because those cat, grep & wc commands all launch processes in exec before our app.

I also tried this, and even it doesn't work, I guess because setting an env var runs a process? Upstart still tracks the wrong pid:

expect fork
script
    NUM_CORES=32
    /path/to/the/app -t $NUM_CORES
end script

I've also tried doing this in an env stanza but apparently those don't run commands:

env num_cores=`cat /proc/cpuinfo | grep processor | wc -l`

Also tried doing this in pre-start, but env vars set there don't have any values in the exec stanza:

pre-start
    NUM_CORES=32
end script

Any idea how to get this NUM_CORES set properly, and still get Upstart to track the correct pid for our app that forks once?


Solution

  • It's awkward. The recommended method is to write an env file in the pre-start stanza and then source it in the script stanza. It's ridiculous, I know.

    expect fork
    
    pre-start script
        exec >"/tmp/$UPSTART_JOB"
        echo "NUM_CORES=$(cat /proc/cpuinfo | grep processor | wc -l)"
    end script
    
    script
        . "/tmp/$UPSTART_JOB"
        /path/to/app -t "$NUM_CORES"
    end script
    
    post-start script
        rm -f "/tmp/$UPSTART_JOB"
    end script
    

    I use the exec line in the pre-start because I usually have multiple env variables and I don't want to repeat the redirection code.

    This only works because the '. ' command is a built-in in dash and thus no process is spawned.