AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 882585
Accepted
tudor -Reinstate Monica-
tudor -Reinstate Monica-
Asked: 2017-11-09 20:26:10 +0800 CST2017-11-09 20:26:10 +0800 CST 2017-11-09 20:26:10 +0800 CST

当 docker 容器运行相同的应用程序(例如 apache2)时,对主机的“pidof”检查失败

  • 772

apache2 初始化脚本会pidof检查 apache 是否已经在运行。

    if pidof $DAEMON > /dev/null 2>&1 ; then
            if [ -e $PIDFILE ] && pidof $DAEMON | tr ' ' '\n' | grep -w $(cat $PIDFILE) > /dev/null 2>&1 ; then
                    AP_RET=2
            else
                    AP_RET=1
            fi
...
            elif [ $AP_RET = 1 ] ; then
                    APACHE2_INIT_MESSAGE="There are processes named 'apache2' running which do not match your pid file which are left untouched in the name of safety, Please review the situation by hand".

(文件:Ubuntu 16.04.3 LTS 上的 /etc/init/apache2 - 为简洁起见截断)

但是,在 docker 主机上,VM 容器中可能已经有 apache。在这种情况下pidof,即使主机上没有运行 apache,也会返回非空。

$ sudo service apache2 stop
$ pidof apache2
32742 32480 32379 32365 31295 31294 31293 31292 31291 31274 31270

这意味着只有当所有带有 apache 的 docker 容器都停止(或尚未启动)时,init 脚本才会成功。因此,无法restart编辑主机上的 apache。

如何解决这种情况,以便可以独立于 VM 重新启动主机的 apache?是否有一个版本pidof只能检测 init 直接拥有的 pid?

docker
  • 2 2 个回答
  • 845 Views

2 个回答

  • Voted
  1. Best Answer
    A.B
    2017-11-10T11:42:19+08:002017-11-10T11:42:19+08:00

    太糟糕了# can't use pidofproc from LSB here,初始化脚本中有一个,没有真正的解释。我仍然认为这个 apache2 脚本有一个值得报告的错误。

    TL; DR:解决方案:替换pidof apache2为pgrep --ns 1 ^apache2$(或者如果这不起作用,pgrep --ns 1 --nslist uts ^apache2$)

    关于命名空间的详细解释,我在找到之前写的一个例子pgrep可以做到以下几点:

    一旦你有“候选人” using pidof,这里有一种方法可以将它们分开:检查它们的命名空间,并将它们与pid 1(init/systemd) 的命名空间进行比较。lxc使用和过程的示例inetd,但这是容器的技术和过程的名称不可知论:

    # lxc-start stretch-amd64
    # pidof inetd
    10285 3372
    # ls -l /proc/1/ns/
    total 0
    lrwxrwxrwx. 1 root root 0 nov.   9 19:49 cgroup -> cgroup:[4026531835]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:49 ipc -> ipc:[4026531839]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:49 mnt -> mnt:[4026531840]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:49 net -> net:[4026531993]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:49 pid -> pid:[4026531836]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:49 pid_for_children -> pid:[4026531836]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:49 user -> user:[4026531837]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:49 uts -> uts:[4026531838]
    # ls -l /proc/3372/ns/
    total 0
    lrwxrwxrwx. 1 root root 0 nov.   9 19:51 cgroup -> cgroup:[4026531835]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:51 ipc -> ipc:[4026531839]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:51 mnt -> mnt:[4026531840]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:51 net -> net:[4026531993]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:51 pid -> pid:[4026531836]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:51 pid_for_children -> pid:[4026531836]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:51 user -> user:[4026531837]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:51 uts -> uts:[4026531838]
    # ls -l /proc/10285/ns/
    total 0
    lrwxrwxrwx. 1 root root 0 nov.   9 19:50 cgroup -> cgroup:[4026532516]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:50 ipc -> ipc:[4026532415]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:50 mnt -> mnt:[4026532410]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:50 net -> net:[4026532418]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:50 pid -> pid:[4026532416]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:50 pid_for_children -> pid:[4026532416]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:50 user -> user:[4026531837]
    lrwxrwxrwx. 1 root root 0 nov.   9 19:50 uts -> uts:[4026532414]
    

    在这里可以清楚地看到pid 3372sharepid 1的命名空间。3372正在主机上运行。10285不共享任何命名空间(好的用户是相同的:容器以root身份运行),所以它在一个容器中。有时主机上运行的某些程序可能由于某种原因(通常与安全相关)而更改了其中的一些,但不应该是 uts(主机名)命名空间。所以这里有一个脚本 usingstat并且在 arg "$1" 中给出进程的名称(例如:set -- inetd或脚本的参数)将只给出相同 uts 命名空间中的进程,通常意味着(相同的)主机。

    pid1uts="$(stat -c %N /proc/1/ns/uts|cut -d' ' -f3)"
    for i in $(pidof "$1"); do
        if [ "$pid1uts" = "$(stat -c %N /proc/$i/ns/uts|cut -d' ' -f3)" ]; then
            echo $i
        fi
    done | xargs -r
    

    在我的示例中,返回3372.

    我解释了如何做到这一点,但为什么要在pgrep有处理它的选项时重新发明轮子:

    # pgrep ^inetd$
    3372
    10285
    # pgrep --ns 1 --nslist uts ^inetd$
    3372
    

    或者对于大多数情况,只是:

    # pgrep --ns 1 ^inetd$
    3372
    
    • 2
  2. Sunil Bhoi
    2017-11-09T22:27:12+08:002017-11-09T22:27:12+08:00

    如果您在主机上的服务在端口 80 上侦听,您可以使用 netstats 找出进程 ID

    #netstat -plan | grep :80
    

    容器进程应与主机上的其他端口号绑定,并在具有 80 端口的容器内部绑定。这样您就可以轻松找出主机进程并将其杀死。

    • 0

相关问题

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve