【问题标题】:How to run a shell script on every request?如何在每个请求上运行 shell 脚本?
【发布时间】:2014-05-18 10:34:23
【问题描述】:

我想在我的 nginx 服务器每次收到任何 HTTP 请求时运行一个 shell 脚本。有什么简单的方法可以做到这一点?

【问题讨论】:

  • 您要解决的实际问题是什么?正如您所解释的那样,这很容易导致更多问题。
  • 我在一个 RPi 上,我希望在我的服务器收到请求时其中一个 LED 闪烁。
  • 您使用什么后端语言/框架?大多数后端语言应该允许您调用 shell 脚本。
  • 我的问题是我是否可以在nginx中修改它。我不想从 PHP 或我可能在每个请求上运行的任何其他语言手动调用 shell 脚本。
  • 不要忘记将您选择的答案标记为已接受;)

标签: shell nginx


【解决方案1】:

您可以通过 nginx.conf 文件中的 Lua 代码执行 shell 脚本来实现此目的。您需要拥有HttpLuaModule 才能执行此操作。

这是一个执行此操作的示例。

location /my-website {
  content_by_lua_block {
    os.execute("/bin/myShellScript.sh")
  } 
}

【讨论】:

  • 这似乎会产生一个 nginx 错误...[alert] 6807#0: waitpid() failed (10: No child processes) - 请参阅serverfault.com/q/432609/86531
  • 似乎来自os.execute()的标准错误进入了nginx错误日志,并且任何标准输出都被丢弃了。 os.execute() 函数返回子进程退出代码,因此该示例将输出一个整数。基于io.popen() 的东西可能更适合通过子进程的标准输出。
  • 还有github.com/juce/lua-resty-shell,但这需要一个外部守护进程。
  • content_by_lua 的使用被标记为不鼓励,因此我相应地更新了您的答案
  • 你能从请求中获取 POST 或 GET 参数以传递脚本吗?
【解决方案2】:

我在这个地址网上找到了以下信息:https://www.ruby-forum.com/topic/2960191

这确实希望您在机器上安装了 fcgiwrap。真的很简单:

sudo apt-get install fcgiwrap

示例脚本(必须可执行)

#!/bin/sh
# -*- coding: utf-8 -*-
NAME=`"cpuinfo"`
echo "Content-type:text/html\r\n"
echo "<html><head>"
echo "<title>$NAME</title>"
echo '<meta name="description" content="'$NAME'">'
echo '<meta name="keywords" content="'$NAME'">'
echo '<meta http-equiv="Content-type"
content="text/html;charset=UTF-8">'
echo '<meta name="ROBOTS" content="noindex">'
echo "</head><body><pre>"
date
echo "\nuname -a"
uname -a
echo "\ncpuinfo"
cat /proc/cpuinfo
echo "</pre></body></html>"

也将其用作包含文件,不仅限于 shell 脚本。

location ~ (\.cgi|\.py|\.sh|\.pl|\.lua)$ {
    gzip off;
    root /var/www/$server_name;
    autoindex on;
    fastcgi_pass unix:/var/run/fcgiwrap.socket;
    include /etc/nginx/fastcgi_params;
    fastcgi_param DOCUMENT_ROOT /var/www/$server_name;
    fastcgi_param SCRIPT_FILENAME /var/www/$server_name$fastcgi_script_name;
}

我发现它对我的工作非常有帮助,我希望它对您的 RaspberryPI 项目有所帮助。

【讨论】:

【解决方案3】:
  1. 安装 OpenResty(OpenResty 只是 Nginx 的增强版,通过插件模块)参考https://openresty.org/en/getting-started.html
  2. 在实例上配置 aws cli
  3. 编写一个从指定 S3 存储桶下载文件的 shell 脚本
  4. 在 nginx.conf 文件中进行必要的更改
  5. 重启nginx服务器

我已经使用 curl 测试了 http 请求,并且文件在各个实例的 /tmp 目录中下载:

curl -I http://localhost:8080/

输出:

curl -I http://localhost:8080/
HTTP/1.1 200 OK
Server: openresty/1.13.6.2
Date: Tue, 14 Aug 2018 07:34:49 GMT
Content-Type: text/plain
Connection: keep-alive 

nginx.conf 文件内容:

worker_processes  1;
error_log logs/error.log;
events {
    worker_connections 1024;
}
http {
    server {
        listen 8080;
        location / {
           default_type text/html;
           content_by_lua '
                ngx.say("<p>hello, world</p>")
           ';
        }

        location / {
            content_by_lua_block{
            os.execute("sh /tmp/s3.sh")
            }
        }

    }
}

【讨论】:

  • 我没有看到任何 shell 脚本输出,而且它说我的文件 /tmp/s3.sh 不存在,即使我创建了该文件并且当我直接执行它时它运行。
  • 我的 os.execute 写入标准输出(我在 nginx 日志中看到它)但我在浏览器中得到了空白页面。
  • ngx.say 按预期写入响应。
【解决方案4】:

您还可以使用 nginx 镜像模块并将其 poxy_pass 到运行任何内容的 Web 脚本,在我的情况下,我只是将它添加到我的主站点位置 {...

mirror /mirror;
mirror_request_body off;

然后是一个名为 mirror 的新位置,我运行了一个执行任何操作的 php 脚本...

location = /mirror {
    internal;
    proxy_pass http://localhost/run_script.php;
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
    proxy_set_header X-Original-URI $request_uri;
}

https://nginx.org/en/docs/http/ngx_http_mirror_module.html

【讨论】:

    猜你喜欢
    • 2012-11-06
    • 2020-12-12
    • 1970-01-01
    • 2021-01-22
    • 2023-02-01
    • 2015-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多