我为 sidekiq 安装了 upstart 服务,如下所示在 wiki 中有说明。
也就是说,我有一个 upstart 脚本,它创建了以下进程:
# skipped other insstructions
script
exec /bin/bash <<'EOT'
source /home/me/.my_env
cd /home/me
exec bin/sidekiq -e production
EOT
end script
服务完美启动,但正如我们所见,sidekiq 的 PID 不等于已知的 PID upstart
。
» initctl status sidekiq
# sidekiq start/running, process 16020
» ps axww|grep sidekiq
# 16181 ? Sl 0:41 sidekiq 3.0.0 me[0 of 3 busy]
该配置适用于除 sidekiq 之外的任何其他 upstart 脚本:
» sudo initctl stop sidekiq
# sidekiq stop/waiting
» ps axww|grep sidekiq
# 16181 ? Sl 0:45 sidekiq 3.0.0 me[0 of 3 busy]
似乎initctl
终止了 bash 进程,它将其视为作业(16020),但底层sidekiq
仍然存在:
» ps axww|grep '16181\|16020'
# 16181 ? Sl 0:45 sidekiq 3.0.0 me[0 of 3 busy]
我究竟做错了什么?
答案1
听起来 sidekiq 正在去中心化,或者至少是分叉。所以你需要关注http://upstart.ubuntu.com/cookbook/#expect,要么找到一个以非守护进程模式运行的 sidekiq 选项,要么添加一个适当的 expect 语句。
答案2
感谢@douglas-leeder 为我指明正确的方向。
sidekiq
既不会妖魔化自己也不会分叉自身(除非-d
明确指定选项。)但在我的 exec 脚本中,我调用了其他进程,upstart 试图将其算作我的一般进程。
expect
选项在这里没有帮助,因为实际的 sidekiq 进程在链中排在第 6 位。更糟糕的是:指定expect fork
会导致 upstart 在停止服务时挂断,而指定会导致expect daemon
在启动服务时挂断。请参阅此回答如何解决 sidekiq 挂断问题。
我最终坚持的解决方案是:需要定义一段post-stop
upstart 脚本,其中包含以下内容:
post-stop script
# ps-grep your PIDS
# for sidekiq:
SQ_PIDS=`ps -Ao pid,command | grep sidekiq | grep -v grep | awk '{ print $1 }' | sed 'N;s/\n/ /g'`
sudo kill -USR1 $SQ_PIDS
sleep 3
sudo kill -9 $SQ_PIDS
sudo rm sidekiq.pid 2>&1 >/dev/null
end script
上述代码将尝试正常关闭 sidekiq 并将其终止。这不是最优雅的解决方案,但它确实有效。