如何通过Nginx触发执行Bash脚本实现Bitbucket自动拉取
解决Nginx接收Bitbucket Webhook时执行Git Pull脚本的问题
我来帮你搞定这个问题——你现在的核心痛点是让Nginx触发Git拉取脚本,同时解决www-data的SSH权限坎儿,我给你两个靠谱的方案,一步步来:
方案一:用fcgiwrap + FastCGI 运行脚本(最稳妥的选择)
fcgiwrap是专门用来把Shell脚本转成FastCGI服务的工具,比自己折腾FastCGI配置简单太多,而且适配Nginx的FastCGI模块完美。
1. 先装fcgiwrap
以Debian/Ubuntu为例,直接用包管理器装:
sudo apt-get install fcgiwrap spawn-fcgi
2. 启动fcgiwrap并绑定套接字
用spawn-fcgi让它以www-data用户运行,这样权限和Nginx一致:
sudo spawn-fcgi -s /var/run/fcgiwrap.sock -u www-data -g www-data -U www-data -G www-data
如果想让它开机自启,你可以写个systemd服务文件,或者用包管理器自带的启动脚本(不同发行版可能有差异,查下文档就行)。
3. 修改你的Nginx配置
把/autopull这个location改成下面这样,专门处理Webhook请求:
server { listen 80; server_name example.ru; root /path/to/root; index index.html; access_log /path/to/logs/nginx-access.log; error_log /path/to/logs/nginx-error.log; location /autopull { # 只允许POST请求(Bitbucket Webhook默认发POST,防止GET误触) limit_except POST { deny all; } # 把请求转发给fcgiwrap的套接字 fastcgi_pass unix:/var/run/fcgiwrap.sock; # 指定要执行的脚本路径 fastcgi_param SCRIPT_FILENAME /path/to/autopull.sh; # 加载Nginx默认的FastCGI参数 include fastcgi_params; } location / { auth_basic "Hello, login please"; auth_basic_user_file /path/to/htpasswd; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; } }
4. 解决www-data的SSH权限问题(重中之重)
这是你之前卡壳的地方,咱一步步来:
- 切换到
www-data用户(注意要用bash,默认可能是sh):sudo su - www-data -s /bin/bash - 生成无密码的SSH密钥(别设密码,不然脚本没法自动跑):
ssh-keygen -t ed25519 -C "www-data@example.ru" - 把生成的公钥(在
~/.ssh/id_ed25519.pub里)复制到Bitbucket仓库的Access keys里(仓库设置 -> Access keys -> Add key)。 - 测试下连接,确保能无密码拉取:
测试完把git clone git@bitbucket.org:你的用户名/你的仓库.git /tmp/test-repo/tmp/test-repo删掉就行。
5. 给脚本加执行权限
别忘给autopull.sh加可执行权限,而且脚本开头要加#!/bin/bash:
chmod +x /path/to/autopull.sh
脚本示例:
#!/bin/bash # 切换到你的静态站点仓库目录 cd /path/to/your/static-site-repo # 拉取最新代码 git pull origin main # 要是有清理缓存、重启服务之类的操作,加在这里就行
方案二:修复Lua模块的问题(如果你偏爱Lua)
之前用Lua没反应大概率是权限或者路径问题,而且没打日志所以查不到错。咱改下配置,把脚本输出打去日志,方便排查:
location /autopull { limit_except POST { deny all; } content_by_lua_block { # 把脚本的标准输出和错误都捕获,写到Nginx日志里 local handle = io.popen("/path/to/autopull.sh 2>&1") local result = handle:read("*a") handle:close() ngx.log(ngx.INFO, "Autopull脚本输出: ", result) ngx.say("脚本执行结果: ", result) } }
之后看Nginx的error.log就能看到脚本为啥没跑成了。不过说实话,Lua执行Shell脚本不是最优解,权限问题排查起来更麻烦,还是优先选方案一。
安全提醒(别漏了!)
- 验证Webhook签名:Bitbucket会给Webhook请求加
X-Hub-Signature头,你可以在脚本里验证这个签名,确保请求确实来自Bitbucket,防止别人瞎触发。 - 限制请求来源:在Nginx的
/autopulllocation里加allow规则,只允许Bitbucket的IP段访问,比如:location /autopull { allow 18.205.93.0/24; allow 13.52.5.0/24; # 其他Bitbucket IP段可以去官方文档查 deny all; # 其他配置... }
内容的提问来源于stack exchange,提问作者Vadim Beglov
相关产品推荐
相关产品推荐

