使用 PHP WebHook 自動部署 BitBucket 伺服器
我已經進行了一些研究,並試圖重現類似於 JONATHAN NICOL 的部落格文章“來自 Bitbucket 的自動 git 部署”的內容。
更新問題
我已經啟用了
exec()
函式輸出的日誌記錄,2>&1
並在我的命令末尾添加了。當我列印返回到 deploy.log 的內容時,我收到以下資訊:
//從
exec('cd /home/apache/www.websitename.org.git && git fetch 2>&1');
( [0] => fatal: Not a git repository (or any parent up to mount point /home) [1] => Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). )
//輸出自
exec('cd /home/apache/www.websitename.org.git && GIT_WORK_TREE=/var/www/html/www.websitename.org /usr/bin/git checkout -f');
Array ( [0] => fatal: Not a git repository (or any parent up to mount point /home) [1] => Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set). )
問題描述:
如果我複制在引用的 PHP Web Hook 腳本中包含的函式內執行的命令的輸出,則在合併
exec()
我時對文件所做的更改將復製到相應的目錄中。我的問題是我想確保在函式中執行的命令實際上正在執行。feature branch``dev``exec()
起初我認為這是由於權限問題,但我從 shell 發出的命令與通過 PHP
exec()
函式發出命令的使用者相同。我似乎無法弄清楚為什麼 Web Hook 腳本生成的命令可以從 apache 使用者的 shell 工作,但是當由作為 apache 執行並生成它們的 PHP 執行時它們不起作用。
環境描述:
我在 RedHat 7.2 機器上執行 BitBucket 伺服器 v4.7.1。該伺服器還包含一個開發環境,我希望在合併特定分支時自動部署文件。
我的網路根目錄是 /var/www/html,apache 可以訪問它。當我執行 a
<?php echo exec('whoami'); ?>
時,輸出是apache
.我正在執行 PHP 5.6.23,我可以從 php 腳本執行 shell 命令。
我的php使用者是apache,apache也有一個shell連接到使用者。
我在 GIT 中的預設分支是
master
,我也有dev
和staging
分支。典型的工作流程是創建一個分支master
並將更改送出到功能分支。然後將該功能分支合併到dev
中,然後staging
最終合併到master
.使用 Nicol 部落格文章的結構和修改後的 BitBucket Repo 用於 bitbucket.org,我已經能夠複製以下內容:
使用以下命令將 GIT 儲存庫複製為鏡像:
作為阿帕奇使用者:
cd /home/apache/ git clone --mirror ssh://git@path.to.bitbucket.local:7999/wn/www.websitename.org.git
然後:
cd /home/apache/www.websitename.org.git GIT_WORK_TREE=/var/www/html/www.websitename.org git checkout -f dev
Apache 對 .git 儲存庫具有適當的權限,apache 可以訪問
git
其中的$PATH
,並且 apache 具有所有權和權限/var/www/html/www.websitename.org
我
dev
在這種情況下進行檢查是因為我在 BitBucket 中的 Web Hook 設置為在功能分支合併dev
並推送到 BitBucket 時做出響應。Bitbucket Server Web Post Hooks Plugin 呼叫的 PHP 腳本類似於以下內容:
更新的程式碼範例
<?php //$repo_name = $_GET['repoName']; //$client = $_GET['client']; //for debug //file_put_contents('deploy.log', serialize($_POST['payload']), FILE_APPEND); //file_put_contents('deploy.log', $_GET['client'], FILE_APPEND); //file_put_contents('deploy.log', $_GET['repoName'], FILE_APPEND); //file_put_contents('deploy.log', print_r($_POST), FILE_APPEND); // Full path to git binary is required if git is not in your PHP user's path. Otherwise just use 'git'. $git_bin_path = '/usr/bin/git'; echo getcwd() . "\n"; $update = false; // Parse data from Bitbucket hook payload //$payload = json_decode($_POST['payload']); if ( isset($_POST['payload']) ) { // old method $payload = $_POST['payload']; } else { // new method $payload = json_decode(file_get_contents('php://input'),false); } /*if(function_exists('exec')) { file_put_contents('deploy.log', print_r("exec enabled",true), FILE_APPEND); }else{ file_put_contents('deploy.log', print_r("exec NOT enabled",true), FILE_APPEND); } if(function_exists('chdir')) { file_put_contents('deploy.log', print_r("chdir enabled",true), FILE_APPEND); }else{ file_put_contents('deploy.log', print_r("chdir NOT enabled",true), FILE_APPEND); } file_put_contents('deploy.log', print_r($payload,true), FILE_APPEND);*/ //set repo name $repo_name = $payload->repository->slug; file_put_contents('/var/www/html/deploy/deploy.log', print_r($repo_name.":",true), FILE_APPEND); $web_root_dir = '/var/www/html/lt/'.$repo_name; $repo_dir = '/home/apache/'.$repo_name.'.git'; $dir = getcwd(); file_put_contents('/var/www/html/deploy/deploy.log',print_r("BEFORECHDIR:".$dir."CHDIRBEFORE\r\n"), FILE_APPEND); file_put_contents('/var/www/html/deploy/deploy.log', print_r("repo".$repo_dir."repo\r\n",true), FILE_APPEND); chdir($repo_dir); file_put_contents('/var/www/html/deploy/deploy.log', print_r("DIR:repo".getcwd()."repo:DIR \r\n",true), FILE_APPEND); $test = chdir($repo_dir); file_put_contents('/var/www/html/deploy/deploy.log', print_r($test,true), FILE_APPEND); if(count($payload->refChanges) == '0'){ $update = false; }elseif($payload->refChanges[0]->refId == 'refs/heads/dev' ){ $update = true; } file_put_contents('/var/www/html/deploy/deploy.log', print_r("This is the update:".$update.": this ends update \r\n",true), FILE_APPEND); if ($update) { file_put_contents('/var/www/html/deploy/deploy.log', print_r("It's an update",true), FILE_APPEND); // Do a git checkout to the web root $cmd1 = $git_bin_path . ' fetch'; $cmd2 = 'GIT_WORK_TREE=' . $web_root_dir . ' ' . $git_bin_path . ' checkout -f '; file_put_contents('/var/www/html/deploy/deploy.log', print_r($cmd1,true), FILE_APPEND); file_put_contents('/var/www/html/deploy/deploy.log', print_r($cmd2,true), FILE_APPEND); $test = chdir($repo_dir); file_put_contents('/var/www/html/deploy/deploy.log', print_r($test,true), FILE_APPEND); exec("cd ".$repo_dir." && ". $cmd1 ." 2>&1",$out1,$outtest); if($outtest !==0 ){ file_put_contents('/var/www/html/deploy/deploy.log', print_r($out1,true), FILE_APPEND); } exec("cd ".$repo_dir." && ". $cmd2 ." 2>&1",$out2,$outtest1); if($outtest1 !==0 ){ file_put_contents('/var/www/html/deploy/deploy.log', print_r($out2,true), FILE_APPEND); } file_put_contents('/var/www/html/deploy/deploy.log', print_r("made it past exec",true), FILE_APPEND); //$test = shell_exec($cmd1); //$test2 = shell_exec($cmd2); file_put_contents('/var/www/html/deploy/deploy.log', print_r($cmd1,true), FILE_APPEND); file_put_contents('/var/www/html/deploy/deploy.log', print_r($cmd2,true), FILE_APPEND); // Log the deployment $commit_hash = exec('cd ' . $repo_dir . ' && ' .$git_bin_path . ' rev-parse --short HEAD'); file_put_contents('/var/www/html/deploy/deploy.log', date('m/d/Y h:i:s a') . " Deployed branch: " . $branch . " Commit: " . $commit_hash . "\n", FILE_APPEND); } ?>
我可能會忽略什麼會導致 PHP 的
exec()
函式在使用時以不足的權限執行,exec()
而不是直接從 php 使用者的 shell 執行?
原來是 RedHat 7.2 下 apache 使用者的 SELinux 權限問題。
我創建了另一個使用者並添加了一個 bash 腳本來執行 git fetch 和 checkout。
我還修改了我的 sudoers 文件以允許 apache 以新創建的使用者身份執行 bash 腳本。