【问题标题】:How to set environment variable in pre-start in Upstart script?如何在 Upstart 脚本的预启动中设置环境变量?
【发布时间】:2012-09-18 14:05:16
【问题描述】:

我们有一个自定义的 C++ 守护程序应用程序,它会分叉一次。因此,我们一直在 Ubuntu 12.04 上的 Upstart 脚本中执行此操作,并且运行良好:

expect fork
exec /path/to/the/app

但是现在我们需要向我们的应用传递一个参数,其中包含运行它的机器上的 CPU 数量:

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

我们的第一次尝试是这样的:

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

虽然使用正确的 -t 值启动我们的应用程序,但 Upstart 会跟踪错误的 pid 值,我假设是因为那些 cat、grep 和 wc 命令在我们的应用程序之前在 exec 中启动所有进程。

我也试过这个,即使它不起作用,我猜是因为设置一个 env var 运行一个进程? Upstart 仍然跟踪错误的 pid:

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

我也尝试在 env 节中执行此操作,但显然那些不运行命令:

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

也尝试在启动前执行此操作,但设置的环境变量在 exec 节中没有任何值:

pre-start
    NUM_CORES=32
end script

知道如何正确设置这个 NUM_CORES,并且仍然让 Upstart 为我们的 fork 一次应用程序跟踪正确的 pid?

【问题讨论】:

    标签: environment-variables upstart


    【解决方案1】:

    这很尴尬。推荐的方法是在 pre-start 节中编写一个 env 文件,然后在 script 节中获取它。这很荒谬,我知道。

    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
    

    我在预启动中使用 exec 行,因为我通常有多个 env 变量并且我不想重复重定向代码。

    这仅适用于 '. ' 命令是内置的破折号,因此不会产生任何进程。

    【讨论】:

    • 超级有帮助!一件事:我认为你仍然需要在脚本块中使用“exec /path/to/app”,如果这是你之前需要的 pid 跟踪。一旦我添加了“exec”,这对我来说效果很好。
    • @CodyA.Ray 完全依赖于正在启动的服务的分叉行为。在我们的例子中,expect daemon 可能是合适的。
    • 对此感激不尽!!挣扎了一个多星期。
    【解决方案2】:

    我会补充

    export NUM_CORES
    

    在“脚本”中为其赋值后。我记得符号链接到非 Bash shell 的 /bin/sh 可能会运行脚本,所以我会避免仅使用 Bash 的构造。

    Re:使用“env”节,它按字面意思传递值,而不使用 shell 约定处理它们。

    【讨论】:

      【解决方案3】:

      根据zram-config的upstart config:

      script
          NUM_CORES=$(grep -c ^processor /proc/cpuinfo | sed 's/^0$/1/')
          /path/to/the/app -t $NUM_CORES
      end script
      

      【讨论】:

      • 问题在于$() 分叉了一个子进程(然后管道导致另一个分叉),这可能会混淆分叉跟踪。如果您在实际守护程序之前分叉两次以上,则较旧的暴发户无法跟踪守护程序进程,然后 respawn 将无法正常工作。这适用于 zram-config 因为它只运行一次并且不需要重生,但它不是通用的。 :) 这就是为什么@mpm 的回答是必要的。
      猜你喜欢
      • 1970-01-01
      • 2016-02-12
      • 2012-01-12
      • 2011-11-26
      • 2016-10-03
      • 2016-11-25
      • 2011-03-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多