如何在每个请求上运行 shell 脚本?

每次我的 nginx 服务器接收到任何 HTTP 请求时,我都想运行一个 shell 脚本。有什么简单的方法吗?

105027 次浏览

可以通过 nginx.conf 文件中的 Lua代码执行 shell 脚本来实现这一点。你需要有 HttpLuaModule才能做到这一点。

这里有个例子。

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

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

这确实需要在机器上安装 fcgiwra,其实就是这么简单:

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 项目。

  1. 安装开放式软件(开放式软件只是 Nginx 的一个增强版本,通过附加模块实现)参考 https://openresty.org/en/getting-started.html
  2. 在实例上配置 aws cli
  3. 编写一个 shell 脚本,从指定的 S3 bucket 下载一个文件
  4. 在 nginx.conf 文件中执行所需的更改
  5. 重新启动 nginx 服务器

我已经测试了 http 请求使用 curl 和 file get download 在 /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

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")
}
}


}
}

您还可以使用 nginx 镜像模块并将其 poxy _ pass 到一个可以运行任何内容的 web 脚本,在我的示例中,我只是将其添加到主站点位置{ ..。

mirror /mirror;
mirror_request_body off;

然后是一个叫镜像的新位置我运行了一个 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

您可以使用 nginx 的 perl 模块,它通常是 repo 的一部分,并且可以很容易地安装。调用系统 curl 命令的示例:

   location /mint {
perl '
sub {
my $r = shift;
$r->send_http_header("text/html");
$r->print(`curl -X POST --data \'{"method":"evm_mine"}\' localhost:7545`);
return OK;
}
';
}

如果您更喜欢 Python 中的完全控制:

  • 创建 /opt/httpbot.py:
#!/usr/bin/env python3
from http.server import HTTPServer, BaseHTTPRequestHandler
import subprocess


class Handler(BaseHTTPRequestHandler):
def do_GET(self):
self._handle()


def do_POST(self):
self._handle()


def _handle(self):
try:
self.log_message("command: %s", self.path)
if self.path == '/foo':
subprocess.run(
"cd /opt/bar && GIT_SSH_COMMAND='ssh -i .ssh/id_rsa' git pull",
shell=True,
)
finally:
self.send_response(200)
self.send_header("content-type", "application/json")
self.end_headers()
self.wfile.write('{"ok": true}\r\n'.encode())


if __name__ == "__main__":
HTTPServer(("127.0.0.1", 4242), Handler).serve_forever()
  • 这里没有并发性/并行性,所以 httpbot一次运行一个命令,没有冲突。
  • 运行 apt install supervisor
  • 创建 /etc/supervisor/conf.d/httpbot.conf:
[program:httpbot]
environment=PYTHONUNBUFFERED="TRUE"
directory=/opt
command=/opt/httpbot.py
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/httpbot.log
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=10
  • 添加到您的 nginx 服务器:
    location /foo {
proxy_pass http://127.0.0.1:4242/foo;
}
  • 跑步:
chmod u+x /opt/httpbot.py


service supervisor status
# If stopped:
service supervisor start


supervisorctl status
# If httpbot is not running:
supervisorctl update


curl https://example.com/foo
# Should return {"ok": true}


tail /var/log/httpbot.log
# Should show `command: /foo` and the output of shell script