我想在我的 docker 镜像中运行一个后台队列:
php artisan queue:work --daemon --sleep=1 --tries=3 &
之后它立即启动httpd
运行 PHPlaravel
应用程序的 Apache。该laravel
应用程序将推送通知发送到 Redis。后台队列工作程序从 Redis 收集消息并通过推送服务发送它们。
这有效并且每秒都会注销。如果后台命令崩溃,我希望它重新启动。根据这个答案https://unix.stackexchange.com/a/223780/72040我可以在后台无限运行命令,如下所示:
while true; do php $QUEUE_WORK; done &
为了测试这一点,我运行了我的容器,docker run
然后docker exec -it
登录并查看:
UID PID PPID C STIME TTY TIME CMD
100000 1 0 0 19:55 ? 00:00:00 httpd -D FOREGROUND
100000 21 1 0 19:55 ? 00:00:00 /bin/sh -e /tmp/scripts/run
100000 22 21 1 19:55 ? 00:00:01 php artisan queue:work --sleep=1 --tries=3
100000 43 1 0 19:55 ? 00:00:00 /usr/bin/cat
100000 50 1 0 19:55 ? 00:00:00 /usr/bin/cat
100000 51 1 0 19:55 ? 00:00:00 /usr/bin/cat
100000 52 1 0 19:55 ? 00:00:00 /usr/bin/cat
100000 53 1 0 19:55 ? 00:00:00 httpd -D FOREGROUND
...
100000 130 0 1 19:57 pts/0 00:00:00 /bin/bash
100000 144 130 0 19:57 pts/0 00:00:00 ps -efww
然后我运行kill 22
查看输出docker run
:
/tmp/scripts/run: line 10: 22 Killed php $QUEUE_WORK
循环不会使进程保持运行。我已经仔细检查循环是否是图像中运行的代码。如果我让循环运行“echo x: sleep 1”,它就可以正常运行。
当我杀死它时,为什么循环没有替换命令?
笔记:该应用程序在 Kubernetes 上部署为多个 Pod,并在httpd
运行状况检查 URL 返回错误或超时时进行监控和自动重新启动。
我不想将队列工作人员部署为单独的 pod 或 sidecar 容器,我想将其作为容器中的后台进程运行,httpd
以便它httpd
以零配置共享应用程序代码。
我对运行进程监视器或其他工具或技术来“保持活力”不感兴趣。
我的问题是为什么 Bash 循环会退出kill
它正在运行的进程?
答案1
设置
我设置了以下内容Dockerfile
:
$ more Dockerfile
From centos
ADD run.sh /tmp/run.sh
RUN chmod +x /tmp/run.sh
ENTRYPOINT ["/tmp/run.sh"]
设置脚本,run.sh
:
$ cat run.sh
while true; do sleep 15 ; echo "background"; done &
while true; do sleep 12 ; echo "foreground"; done
建造它:
$ docker build -t sleeper .
Sending build context to Docker daemon 7.791 MB
Step 1/4 : FROM centos
---> 49f7960eb7e4
Step 2/4 : ADD run.sh /tmp/run.sh
---> b4099de53780
Removing intermediate container 1ce8e3a1dac5
Step 3/4 : RUN chmod +x /tmp/run.sh
---> Running in e410429a6cba
---> 06789467e636
Removing intermediate container e410429a6cba
Step 4/4 : ENTRYPOINT /tmp/run.sh
---> Running in ad8b847b505f
---> a2415df63f99
Removing intermediate container ad8b847b505f
Successfully built a2415df63f99
例子
然后启动它:
$ docker run -dit sleeper
28c19c338e6e6177529cf989f42c7f14b17f1c705a61f5244d5350f0ab8f8364
然后它重复运行并显示:
foreground
background
foreground
background
现在,当我观看它时,我可以看到它仍在运行,尽管sleep
命令最终“死亡”:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
28c19c338e6e sleeper "/tmp/run.sh" About a minute ago Up About a minute focused_lumiere
从上面我们可以看到这个容器已经启动超过1分钟了。这是ps auxf
容器内部的样子:
$ ps auxf
...
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 24 0.0 0.1 11828 2964 pts/1 Ss 16:00 0:00 /bin/bash
root 58 0.0 0.1 51712 3432 pts/1 R+ 16:01 0:00 \_ ps auxf
root 1 0.0 0.1 11692 2572 pts/0 Ss+ 15:58 0:00 /bin/bash /tmp/
root 5 0.0 0.1 11696 2272 pts/0 S+ 15:58 0:00 /bin/bash /tmp/
root 56 0.0 0.0 4368 636 pts/0 S+ 16:01 0:00 \_ sleep 15
root 57 0.0 0.0 4368 664 pts/0 S+ 16:01 0:00 sleep 12
sleep 15
现在,如果我们像这样取消背景:
$ kill 56
并运行另一个docker ps
:
$ docker ps
...
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 24 0.0 0.1 11828 2964 pts/1 Ss 16:00 0:00 /bin/bash
root 60 0.0 0.1 51712 3344 pts/1 R+ 16:01 0:00 \_ ps auxf
root 1 0.0 0.1 11692 2572 pts/0 Ss+ 15:58 0:00 /bin/bash /tmp/
root 5 0.0 0.1 11696 2272 pts/0 S+ 15:58 0:00 /bin/bash /tmp/
root 59 0.0 0.0 4368 636 pts/0 S+ 16:01 0:00 \_ sleep 15
root 57 0.0 0.0 4368 664 pts/0 S+ 16:01 0:00 sleep 12
我们可以看到保护后台进程的 while 循环sleep 15
已经完成了它的工作并重新启动了另一个sleep 15
.