美文网首页
万爷遇到的一个小问题

万爷遇到的一个小问题

作者: 董泽润 | 来源:发表于2018-12-20 17:21 被阅读177次

    现象

    发部系统发布 mysql 任务,deploy.py 部署脚本一直没有返回,直到超时被杀掉。实际上 mysql 早己部署完成了。

    部署脚本会调用 mysql.sh shell 脚本去启动 mysql, 由于要放到后台运行,所以在 mysqld_safe 最后加了个 &

    cd /home/qboxserver/mysql_pxc_3358/_package/ ;
    (./bin/mysqld_safe --defaults-file=/home/qboxserver/mysql_pxc_3358/_package/my.conf  --wsrep-new-cluster &)
    

    现场

    通过 ps axjf 查看所有相关进程,也没有敏感信息直接截图了

    ps axjf
    可以看到组 gid 都是 16291,但是 mysqld_safe 的父进程己经是 1 了,被系统接管。但是 deploy.py 的 shell 子进程 20020 却是处于 Z 状态,也就是僵尸进程。kill 跟本杀不掉,只能通过杀父进程的方式来回收僵尸进程。

    分析

    分别通过 lsof -p 查看 deploy.py 进程和 mysql 进程,看看打开发哪些文件


    deploy.py 进程 lsof mysql 进程 lsof

    可以看到 deploy.py 有个文件描术符 8,和 mysql 打开的 13 是同一个文件,inode 都是 50994157,到这问题就很明确了。mysqld 不该继承无用的 fd,这也就是 c 语言中 close on exec 的用处。

    解决

    知道原因了,解决方案却不好办。deploy.py 通过 os.system 去执行的 mysql.sh 脚本,查看文档 os.system 好像没有类似 close on exec 的参数。并且如果打开的 fd 全关掉,mysql.sh 的输出日志部署系统会看不到。暂时的方案其实很丑:

    closefd () {
    for fd in $(ls /proc/$$/fd); do
      case "$fd" in
        *)
          eval "exec $fd>&-"
          ;;
      esac
    done
    }
    

    创建一个函数 closefd,作用就是关闭当前进程打开的所有文件

    ls | closefd;cd /home/qboxserver/mysql_pxc_3358/_package/ &&
     (./bin/mysqld_safe --defaults-file=/home/qboxserver/mysql_pxc_3358/_package/my.conf  --wsrep-new-cluster 1>/tmp/aaaaaaaaaa 2>&1 &)
    

    我们知道 shell 里 | 管理会创建新的进程,那索性 ls | 开个管道,在新的进程里调用 closefd 关闭所有 fd 就能达到目的。

    问题到此解决了,却也丑巴拉即的..........

    更新20181221

    原来 Popen 有 close_fds 选项... 就说么,这么牛逼的坑肯定早有人踩过...


    Popen

    相关文章

      网友评论

          本文标题:万爷遇到的一个小问题

          本文链接:https://www.haomeiwen.com/subject/hbtukqtx.html