我正在尝试设置 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 可能不同。比较两种情况下
id
、id -r -u
、id -r -g
、id -r -G
、id -u
、id -g
和的输出。id -G
- 工艺限制:可能是您的 upstart 脚本有更严格的限制。尝试放置一个
ulimit -a
来进行比较。 - 壳的奇异性:不太可能,但 upstart 使用,
sh
而您的用户的 shell 最有可能是bash
或zsh
。尝试从 运行成功的命令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 工具,在两个环境中运行它并对输出文件进行差异化:
- https://launchpad.net/procenv/
- http://ifdeflinux.blogspot.co.uk/2012/10/procenv-and-process-environment.html
这在 ubuntu raring 和 debian sid 档案(和 FreeBSD)中可用。