3

我在 apache2 中使用外部重写程序 (prg) 运行重写映射,这可能会产生错误并死掉。当重写映射不再运行时,系统显然无法正常运行。

所以我想启动一个简单的包装外壳脚本,它本身执行地图程序(用 php 编写)并在它死时重新启动它:

#!/bin/bash
until /usr/bin/php /somepath/mymap.php; do
  echo "map died but i will restart it right away!" 
done

如果我在 shell 中手动尝试,它工作正常,但是当由网络服务器启动时它不起作用。

...然后通过其标准输入和标准输出文件句柄与重写引擎通信。对于每个映射函数查找,它将在标准输入上接收作为以换行符结尾的字符串来查找的键。然后它必须将查找到的值作为标准输出上的换行符终止的字符串或四字符字符串“NULL”返回,如果它失败......

原因对我来说似乎很清楚。第一个脚本采用标准输入,但不将其重定向到子脚本。

我想我需要以某种方式定义一个描述符,exec并正确地重定向脚本的标准输入/标准输出。但是我该怎么做呢?

4

3 回答 3

3

一些脚本“手动”执行并且在间接执行时(通过 cron 或从 apache)不起作用,这是一个常见问题。

通常根本原因是以下之一:

  1. 您的脚本需要一些额外的环境变量(PATH、LD_LIBRARY_PATH 等)
  2. 你的脚本需要终端

首先要做的是获取一些调试信息,所以添加到您的脚本中:

env > /tmp/$0.env # get environment

并获得标准错误:

... /usr/bin/php /somepath/mymap.php 2>/tmp/$0.stderr ...

这可能会引导您找到解决方案。

如果您的脚本需要终端并且您无法修复它,您可以通过 gnu 屏幕运行您的脚本。

祝你好运。

于 2012-01-03T19:57:59.273 回答
2

Michał Šrajer给出了一个非常常见的问题原因(环境)。您当然应该确保环境设置得很好,因为 Apache 严格设置自己的环境并且不会传递任何继承的垃圾值;它只传递它配置传递的内容(SetEnvPassEnv指令,IIRC)。

另一个问题是你认为你的映射过程会失败;这令人担忧。此外,这是另一个问题的症状,我认为这是主要问题。

map 进程第一次运行时,它会从 web 服务器读取请求,但是如果映射失败,你重新运行它——但是 web 服务器仍在等待原始请求的输出,而 map 进程正在等待对于输入,所以出现了僵局。

请注意,子进程会自动继承其父进程的标准输入和标准输出,除非您对其进行更改。

如果您认为事情可能会失败,您将需要捕获标准输入,以便在重新运行程序时,您可以重新提供输入(尽管为什么它会在第一次失败时第二次工作是一个单独的谜) .

也许:

if tee /tmp/xx.$$ | /usr/bin/php /somepath/mymap.php
then : OK
else
     until /usr/bin/php /somepath/mymap.php < /tmp/xx.$$
     do echo "map died but I will restart it right away!"
     done
fi
rm -f /tmp/xx.$$

未解决的问题包括:

  • 您应该添加陷阱以确保删除临时文件;
  • 您可能不应该/tmp用作目录;
  • 在整个脚本终止之前,消息可能不会发送到 Web 服务器并从那里发送到客户端浏览器,因此回显的消息只会弄乱响应的开始;
  • 失败次数没有限制;
  • 没有记录失败;
  • 没有尝试修复导致失败的问题;
  • 可能还有其他我还没有想到的。
于 2012-01-03T20:14:50.927 回答
1

until不是一个有效的关键字,你可能给它起了别名,并且别名在脚本上不起作用。我的错,似乎是。

无论如何,这就是你想要做的:

while true; do
    /usr/bin/php /somepath/mymap.php
done

如果这也失败了,那么是的,要么你的程序需要一个终端,要么你的环境中缺少一些东西。

于 2012-01-03T20:23:32.350 回答