如何编写包装器 - 避免使用子 shell - apache2 重写映射或一般 shell 脚本的脚本?

发布于 2024-12-24 18:36:18 字数 608 浏览 0 评论 0原文

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

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

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

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

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

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

我想我需要以某种方式使用 exec 定义一个描述符并正确重定向脚本的 stdin/stdout 。但我该怎么做呢?

I am running a rewrite map with an external rewrite program (prg) in apache2 that may produce an error and die.
When the rewrite map is not running any more the system obviously doesn't function properly.

So I wanted to start a simple wrapper shell script that itself executes map program (which is written in php) and restarts it if it dies:

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

If I try that in the shell by hand, it works fine, however it does not work when started by the webserver.

...and then communicates with the rewriting engine via its stdin and
stdout file-handles. For each map-function lookup it will receive the
key to lookup as a newline-terminated string on stdin. It then has to
give back the looked-up value as a newline-terminated string on stdout
or the four-character string ``NULL'' if it fails...

The reason seems pretty clear to me. The first script takes stdin but doesn't redirect it to the sub script.

I guess I somehow need to define a descriptor using exec and redirect stdin/stdout of the scripts properly. But how do I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

魄砕の薆 2024-12-31 18:36:18

一个常见的问题是,某些脚本可以“手动”执行,但在间接执行时(通过 cron 或从 apache)则不起作用。

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

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

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

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

并获取 stderr:

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

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

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

祝你好运。

It's a common problem that some script works executed "by hand" and do not work when executed indirectly (via cron or from apache).

Usually the root cause is one of:

  1. your script needs some extra environment varaible (PATH, LD_LIBRARY_PATH, etc.)
  2. your script requires terminal

First thing to do is to grab some debug info, so add to your script:

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

and get stderr:

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

This may lead you to the solution.

If your script requires terminal and you cannot fix it you can run your script via gnu screen.

Good luck.

鹿童谣 2024-12-31 18:36:18

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 服务器,然后再发送到客户端浏览器,因此回显的消息只会扰乱响应的开始;
  • 失败次数没有限制;
  • 没有失败记录;
  • 没有尝试修复导致失败的问题;
  • 可能还有其他我还没有想到的。

Michał Šrajer has given one very common cause of trouble (environment). You should certainly be sure that the environment is sufficiently well set up, because Apache sets its own environment rigorously and does not pass on any inherited junk values; it only passes what it is configured to pass (SetEnv and PassEnv directives, IIRC).

Another problem is that you think your mapping process will fail; that's worrying. Further, it is symptomatic of yet another problem, which I think is the main one.

The first time the map process is run, it will read the request from the web server, but if the mapping fails, you rerun it - but the web server is still waiting for the output from the original request, and the map process is waiting for the input, so there's an impasse.

Note that a child process automatically inherits the standard input and standard output of its parent unless you do something to change it.

If you think things might fail, you'll need to capture the standard input so that when you rerun the program, you can resupply the input (though why it would work on the second time when it failed on the first is a separate mystery).

Maybe:

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.$

Unresolved issues include:

  • You should add traps to ensure that the temporary file is removed;
  • You should probably not use /tmp as the directory;
  • The messages probably do not get sent to the web server and from thence to the client browser until the overall script terminates, so the echoed messages simply mess up the start of the response;
  • There is no limit on the number of failures;
  • There is no logging of the failures;
  • There is no attempt to fix the problem that caused the failure;
  • And there are probably others I've not thought of yet.
海拔太高太耀眼 2024-12-31 18:36:18

until 不是有效的关键字,您可能为其添加了别名,而别名在脚本上不起作用。 我的错误,看来是这样。

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

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

如果这也失败了,那么是的,您的程序需要一个终端,或者您的环境中缺少某些内容。

until is not a valid keyword, you probably have it aliased and aliases do not work on scripts. my mistake, it seems it is.

regardless, this is what you want to do:

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

if this also fails then yes, either your program expects a terminal or you have something missing in your env.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文