如何解决壳中的 Gearman 工人像僵尸一样挂起
我在以 Gearman 开头的 shell 脚本中有一个 perp 工作线程,如下所示:
runuid -s gds \
/usr/bin/gearman -h 127.0.0.1 -t 1000 -w -f gds-rel \
-- xargs /home/gds/gds-rel-worker.sh < /dev/null 2>/dev/null
worker 只进行一些输入验证并调用另一个 shell 脚本 run.sh,该脚本调用 bash、curl、Terragrunt、terraform、Ansible 和 gcloud 来供应和更新 GCP 中的资源,如下所示:
./run.sh --release 1.2.3 2>&1 >> /var/log/gds-release
该脚本旨在无人值守的情况下运行。我遇到的问题是,在作业成功完成后(即 shell 脚本 run.sh 和 gds-rel-worker.sh),Gearman 作业仍在执行,因为子进程变成了僵尸进程(请参阅下面的最后一行)。
root 144748 1 0 Apr29 ? 00:00:00 perpboot -d /etc/perp
root 144749 144748 0 Apr29 ? 00:00:00 \_ tinylog -k 8 -s 100000 -t -z /var/log/perp/perpd-root
root 144750 144748 0 Apr29 ? 00:00:00 \_ perpd /etc/perp
root 2492482 144750 0 May14 ? 00:00:00 \_ tinylog (gearmand) -k 10 -s 100000000 -t -z /var/log/perp/gearmand
gearmand 2492483 144750 0 May14 ? 00:00:08 \_ /usr/sbin/gearmand -L 127.0.0.1 -p 4730 --verbose INFO --log-file stderr --keepalive --keepalive-idle 120 --keepalive-interval 120 --keepalive-count 3 --round-robin --threads 36 --worker-wakeup 3 --job-retries 1
root 2531800 144750 0 May14 ? 00:00:00 \_ tinylog (gds-rel-worker) -k 10 -s 100000000 -t -z /var/log/perp/gds-rel-worker
gds 2531801 144750 0 May14 ? 00:00:00 \_ /usr/bin/gearman -h 127.0.0.1 -t 1000 -w -f gds-rel -- xargs /home/gds/gds-rel-worker.sh
gds 2531880 2531801 0 May14 ? 00:00:00 \_ [xargs] <defunct>
到目前为止,我已经将问题追溯到 run.sh,因为如果我用更简单的东西替换它的调用(例如 echo "Hello"; sleep 5),worker 不会挂起。不幸的是,我不知道是什么导致了问题。脚本 run.sh 相当长且复杂,但到目前为止一直工作没有问题。跟踪工作进程我看到了这个:
getpid() = 2531801
write(2,"gearman: ",9) = 9
write(2,"gearman_worker_work",19) = 19
write(2," : ",3) = 3
write(2,"gearman_wait(GEARMAN_TIMEOUT) ti"...,151) = 151
write(2,"\n",1) = 1
sendto(5,"\0REQ\0\0\0'\0\0\0\0",12,MSG_NOSIGNAL,NULL,0) = 12
recvfrom(5,"\0RES\0\0\0\n\0\0\0\0",8192,NULL) = 12
sendto(5,"\0REQ\0\0\0\4\0\0\0\0",0) = 12
poll([{fd=5,events=POLLIN},{fd=3,events=POLLIN}],2,1000) = 1 ([{fd=5,revents=POLLIN}])
sendto(5,"\0RES\0\0\0\6\0\0\0\0\0RES\0\0\0(\0\0\0QH:terra-"...,NULL) = 105
pipe([6,7]) = 0
pipe([8,9]) = 0
clone(child_stack=NULL,flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,child_tidptr=0x7fea38480a50) = 2531880
close(6) = 0
close(9) = 0
write(7,"1.2.3\n",18) = 6
close(7) = 0
read(8,"which: no terraform-0.14 in (/us"...,1024) = 80
read(8,"Identity added: /home/gds/.ssh/i"...,1024) = 54
read(8,0x7fff6251f5b0,1024) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
--- SIGCHLD {si_signo=SIGCHLD,si_code=CLD_EXITED,si_pid=2531880,si_uid=1006,si_status=0,si_utime=0,si_stime=0} ---
read(8,
因此,即使子进程已成功完成并且可能已关闭它,工作进程仍会继续读取标准输出。任何想法如何捕捉导致此问题的原因?
解决方法
我能够解决它。脚本 run.sh 正在启动 ssh-agent,这会打开一个套接字,并且由于 Gearman 重定向了所有输出,即使在脚本成功完成后,worker 仍会继续读取打开的文件描述符。
我通过检查 Gearman 工作进程挂起后打开的文件描述符找到了它:
# ls -l /proc/2531801/fd/*
lr-x------. 1 gds devops 64 May 17 11:26 /proc/2531801/fd/0 -> /dev/null
l-wx------. 1 gds devops 64 May 17 11:26 /proc/2531801/fd/1 -> 'pipe:[9356665]'
l-wx------. 1 gds devops 64 May 17 11:26 /proc/2531801/fd/2 -> 'pipe:[9356665]'
lr-x------. 1 gds devops 64 May 17 11:26 /proc/2531801/fd/3 -> 'pipe:[9357481]'
l-wx------. 1 gds devops 64 May 17 11:26 /proc/2531801/fd/4 -> 'pipe:[9357481]'
lrwx------. 1 gds devops 64 May 17 11:26 /proc/2531801/fd/5 -> 'socket:[9357482]'
lr-x------. 1 gds devops 64 May 17 11:26 /proc/2531801/fd/8 -> 'pipe:[9369888]'
然后在德国工人继续阅读的文件描述符8中使用文件节点识别管道的进程:
# lsof | grep 9369888
gearman 2531801 gds 8r FIFO 0,13 0t0 9369888 pipe
ssh-agent 2531899 gds 9w FIFO 0,13 0t0 9369888 pipe
最后列出了 ssh-agent 打开的文件,并找到了文件描述符 3 背后的内容:
# ls -l /proc/2531899/fd/*
lrwx------. 1 root root 64 May 17 11:14 /proc/2531899/fd/0 -> /dev/null
lrwx------. 1 root root 64 May 17 11:14 /proc/2531899/fd/1 -> /dev/null
lrwx------. 1 root root 64 May 17 11:14 /proc/2531899/fd/2 -> /dev/null
lrwx------. 1 root root 64 May 17 11:14 /proc/2531899/fd/3 -> 'socket:[9346577]'
# lsof | grep 9346577
ssh-agent 2531899 gds 3u unix 0xffff89016fd34000 0t0 9346577 /tmp/ssh-0b14coFWhy40/agent.2531898 type=STREAM
作为解决方案,我在退出 run.sh 脚本之前添加了杀死 ssh-agent,现在没有由于僵尸进程而挂起的作业。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。