【问题标题】:In Apache/PHP how to run a process that will be independent and survive apache restart on linux在 Apache/PHP 中,如何运行一个独立的进程并在 linux 上重启 apache
【发布时间】:2018-08-06 11:17:45
【问题描述】:

我正在尝试启动一个 php(在 apache 下)进程(通过从浏览器调用 apache),这将在关闭 apache 服务器后继续存在(sudo service apache2 stop)。即使我确保创建的进程没有父进程(父进程 1),并且有它自己的会话,但不知何故,当我停止 apache(或重新启动 apache)时,进程还是死了

我创建了一个 test.php 文件:

<?php
exec('setsid nohup sleep 1000 > /dev/null 2>/dev/null &');
?>

当运行对该 test.php 执行 HTTP GET 时,确实我们会立即得到 OK 响应,并且该过程仍然存在。 但是,当我们这样做时:

sudo service apache2 stop

睡眠进程终止。 当进程不属于其组或会话并且进程不是子进程时,如何杀死进程?

【问题讨论】:

  • “我正在尝试从 php (+apache) 启动一个进程” - 你是通过浏览器调用脚本,还是通过 Apache?
  • 没错。简单的 apache 服务器,它调用我在问题中编写的 php 脚本。
  • cron 是一个选项吗?如果例如,您可以每分钟检查一次。数据库表中有条目然后被处理。如果是关于文件,想象一下使用this answer
  • 为什么是 cron?为什么选择数据库?我只想要一个可以保持活力的简单过程(孤儿?)。就这么简单。我不明白 apache 如何拥有终止进程的权利/特权。也许apache保存了一个由php生成的进程的PID列表,并在关闭期间一一杀死它们?
  • 尝试创建一个进程,分叉它并杀死父进程。那时不应该与 Apache 有任何联系。我记得我在类似的情况下使用过这种方法(不记得具体是什么)。基本上你可以通过跟踪它们的ppid 来判断哪些进程是由 Apache 产生的,但是如果父进程不再存在,你就会中断链。

标签: php linux apache process


【解决方案1】:

Apache 可能会有一个生成进程的列表并单独杀死它们,而不是作为一个组。在这种情况下,列表中的所有进程都将是kill(2)ed。但请参阅下面的下一段以了解可能性。

查看kill(2) 系统调用的手册页。在 ERRORS 部分,失败的唯一可能性是:

  • EINVAL,表示传递了无效的信号编号。不适用于此处。

  • ESRCH,进程(或进程组)不存在。也不适用。

  • EPERM,您无权发送信号。这适用于这里,但唯一允许您向其发送信号的进程(这与进程层次结构或父母关系无关)是使用真实/保存的用户 ID 运行的进程,该用户 ID 等于发送者进程的有效用户 ID。因此,由于 Apache 有一个它启动的所有进程的注册表,它能够杀死该进程是正常的。

无论如何,您是否尝试过创建一个进程,从该进程创建一个子进程,并在孙子进程中执行setsid?这样,Apache 进程就没有机会将其注册到派生进程列表中。我没有尝试过,但它可以工作。

来自 FreeBSD kill(2) 手册页:

让进程有权向指定的进程发送信号 通过 pid,用户必须是超级用户,或者 真实或保存的用户 ID 接收进程必须匹配真实或有效的用户ID 发送进程。 一个例外是信号SIGCONT,它可能 总是被发送到与发送者具有相同会话 ID 的任何进程。

(重点是我的)在linux中,几乎是一样的,除了

...(如果是发送进程)在目标进程的用户命名空间中具有CAP_KILL 能力...

但这不适用于这里。

【讨论】:

  • 我尝试修改 php exec() 命令来运行执行“setsid nohup sleep 1000”(2 级)的 .sh 脚本,但我没有尝试创建进程,这会创建另一个子进程,然后使用 setsid 创建另一个子进程。需要这么多关卡吗?两级还不够吗?
猜你喜欢
  • 1970-01-01
  • 2010-09-13
  • 1970-01-01
  • 2018-05-14
  • 1970-01-01
  • 2020-03-05
  • 2019-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多