当我的 upstart 作业将任何先前的日志文件移动到备份时,它在预启动时失败:
pre-start script
mv -f $LOGDIR/$LOGFILE $LOGDIR/$LOGFILE.bak
touch $LOGDIR/$LOGFILE
end script
mv
如果前一个日志文件不存在,我预计会失败,因此添加了touch
以确保脚本主体中的最后一条命令返回 0。
但是,如果脚本在日志目录中没有以前的日志文件时运行,则会在预启动时失败:
Jan 9 17:21:14 ip-172-30-1-54 kernel: [ 250.154908] init: myscript state changed from starting to security
Jan 9 17:21:14 ip-172-30-1-54 kernel: [ 250.154951] init: myscript state changed from security to pre-start
Jan 9 17:21:14 ip-172-30-1-54 kernel: [ 250.155652] init: myscript pre-start process (1425)
Jan 9 17:21:14 ip-172-30-1-54 kernel: [ 250.157167] init: myscript pre-start process (1425) terminated with status 1
Jan 9 17:21:14 ip-172-30-1-54 kernel: [ 250.157280] init: myscript goal changed from start to stop
如果我再次启动该脚本,它会成功通过预启动并进入主脚本主体:
Jan 9 17:21:29 ip-172-30-1-54 kernel: [ 265.444327] init: myscript state changed from starting to security
Jan 9 17:21:29 ip-172-30-1-54 kernel: [ 265.444371] init: myscript state changed from security to pre-start
Jan 9 17:21:29 ip-172-30-1-54 kernel: [ 265.445359] init: myscript pre-start process (1431)
Jan 9 17:21:29 ip-172-30-1-54 kernel: [ 265.447203] init: myscript pre-start process (1431) exited normally
Jan 9 17:21:29 ip-172-30-1-54 kernel: [ 265.447249] init: myscript state changed from pre-start to spawned
Jan 9 17:21:29 ip-172-30-1-54 kernel: [ 265.447874] init: myscript main process (1434)
Jan 9 17:21:29 ip-172-30-1-54 kernel: [ 265.447896] init: myscript state changed from spawned to post-start
Jan 9 17:21:29 ip-172-30-1-54 kernel: [ 265.447972] init: myscript state changed from post-start to running
从这个行为中,我推断脚本主体每次执行一行,并且任何失败都会终止脚本(非常像make
)。文档该script
指令没有给出任何指导:
允许指定要执行的多行 shell 代码块。块以 end script 结束。
有人能证实或否认我的观点吗?如果证实,我只需运行一个独立的 shell 脚本即可exec
。如果否认,我需要在其他地方寻找问题。
答案1
我的印象是 Upstart 使用整个脚本运行/bin/sh
,并在出错时退出(set -e
或命令行选项-e
)。也就是说,如果任何未检查退出代码的命令返回非零退出代码,则立即终止脚本。
事实上,给定一个配置:
description "Testing upstart"
task
script
set -o > /tmp/blah
end script
可以找到以下选项设置:
Current option settings
errexit on
noglob off
ignoreeof off
interactive off
monitor off
noexec off
stdin off
xtrace off
verbose off
vi off
emacs off
noclobber off
allexport off
notify off
nounset off
nolog off
debug off
虽然我对它第二次如何运行感到困惑,因为对于任何形式的配置:
pre-start script
false
# any number of commands
end script
正如预期的那样,之后的所有命令false
均未执行,因此该touch
命令永远不应该执行,并且mv
后续运行也应该失败。
set -e
这并不罕见 - 您会发现,例如,包维护脚本也会在启用它的情况下运行。这就是为什么您会看到以下形式的样板:
command that could fail but is not essential || true
的确,食谱上也这么说:
如果某个
script
部分的行为似乎很奇怪,则可能是其中一个命令失败了。请记住,Upstartscript
使用 运行每个部分/bin/sh -e
。这意味着如果任何简单命令失败,shell 将退出。