upstart 是否将整个脚本主体传递给 shell 执行还是逐行处理?

upstart 是否将整个脚本主体传递给 shell 执行还是逐行处理?

当我的 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 将退出。

另请参阅:章节11.58.118.7

相关内容