Upstart 脚本与命令行:为什么行为上有这种差异?

Upstart 脚本与命令行:为什么行为上有这种差异?

我正在尝试设置 Tomcat 以从 upstart 启动。我发现以下方法有效:

  description "Tomcat Server"

  start on runlevel [2345]
  stop on runlevel [!2345]
  respawn
  respawn limit 10 5

  setuid tomcat

  env JAVA_HOME=/usr/lib/jvm/default-java
  env CATALINA_HOME=/opt/apache-tomcat-7.0.34

  script
    chdir $CATALINA_HOME
    exec $CATALINA_HOME/bin/catalina.sh run
  end script

但是如果我删除了chdir,tomcat 会启动,但在加载时会出现大量FileNotFound异常.wars。(即:它们.wars本身确实加载,但它们在加载时抛出异常。)

注意此行为不同的从命令行调用时看到的内容catalina.sh。从命令行调用,我可以运行/opt/apache-tomcat-7.0.34/bin/catalina.sh run 来自任何目录(无需 chdiring)一切都很好。

那么为什么chdir我的 upstart 脚本中这是必需的? (upstart 环境与我的命令行环境有何不同?)


当我不使用 chdir 时,我看到 upstart 的错误示例:

Feb 22, 2013 3:00:11 AM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive my-war.war
log4j:ERROR setFile(null,true) call failed.
java.io.FileNotFoundException: my-war.log (Permission denied)
    at java.io.FileOutputStream.open(Native Method)

答案1

这是一个写入权限问题。用户 tomcat 无法在其尝试创建日志文件的位置创建日志文件。其尝试创建日志文件的位置因您启动 tomcat 的方式而异。

您的日志中的这一部分引起了我的注意:

java.io.FileNotFoundException:my-war.log(权限被拒绝)在 java.io.FileOutputStream.open(本机方法)

它表示不允许用户 (tomcat) 创建文件 my-war.log。以下是不同的场景:

使用 chdir 的 Upstart

Upstart 首先将目录更改为 $CATALINA_HOME。用户 tomcat 被允许在那里创建文件。因此一切正常。

没有 chdir 的 Upstart

Upstart 以 root 身份运行,因此默认目录为 /。用户 tomcat 无权在该目录下创建文件。因此您会收到权限被拒绝的错误。

从你的主目录运行 tomcat

现在,您可以从主目录以自己的身份运行 tomcat。您拥有自己目录的写入权限。因此,一切又恢复正常。

答案2

我无法访问具有setuid支持的 upstart 版本,但是在您的情况下我会这样做。

这看起来像是一个环境差异问题。最有可能是从 upstart 运行时未设置的环境变量。可能是setuid没有设置$USER$HOME

因此,我建议您比较环境。一种简单易行的方法是像这样修改您的初始化脚本并重新启动作业。

  script
    env > /tmp/env-upstart.log
    chdir $CATALINA_HOME
    exec $CATALINA_HOME/bin/catalina.sh run
  end script

env > /tmp/env-console.log然后,当您通常从控制台启动它时,也会运行(如果您正在使用sudo,则使用 来执行sudo env)。

然后比较两个/tmp/env-upstart.log/tmp/env-console.log文件(对它们进行排序并用打开它们vimdiff),应该很容易找到env-upstart另一个文件中缺少哪个变量(或者设置为您意想不到的内容)。

更新 1

如果您仍然收到错误,我将检查以下内容:

  • 用户权限:有效/真实用户 ID 可能不同。比较两种情况下idid -r -uid -r -gid -r -Gid -uid -g和的输出。id -G
  • 工艺限制:可能是您的 upstart 脚本有更严格的限制。尝试放置一个ulimit -a来进行比较。
  • 壳的奇异性:不太可能,但 upstart 使用,sh而您的用户的 shell 最有可能是bashzsh。尝试从 运行成功的命令sh
  • 调试脚本:如果您仍然非常非常困惑,请catalina.sh以调试模式运行。这就像从 upstart 运行它一样简单,如下所示:

    exec /bin/sh -x $CATALINA_HOME/bin/catalina.sh run 2>/tmp/catalina-upstart.log
    

    然后,您可以比较两个调试日志,并可能发现两个脚本执行的不同之处。

答案3

是的,这与权限有关。但与 Upstart 无关。这是因为在 'catalina.sh start' 中,即在 'start' 部分,真正的命令是:

  ...
  -Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
  org.apache.catalina.startup.Bootstrap "$@" start \
  >> "$CATALINA_OUT" 2>&1 "&"

这里输出日志是完全赋值的,而RUN部分没有“$CATALINA_OUT”,这会导致上面提到的写入权限问题,也就是说,如果没有指定具体的输出文件路径,输出要么进入logs文件,要么按照你的.war代码来操作。这种不明确的日志赋值会导致不确定的权限问题。

答案4

为了获得在命令行上运行服务器与在 Upstart 下运行服务器之间所有环境元素的完整转储,请尝试安装我的 procenv 工具,在两个环境中运行它并对输出文件进行差异化:

这在 ubuntu raring 和 debian sid 档案(和 FreeBSD)中可用。

相关内容