Php

使用 PHP WebHook 自動部署 BitBucket 伺服器

  • July 25, 2019

我已經進行了一些研究,並試圖重現類似於 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 發出的命令與通過 PHPexec()函式發出命令的使用者相同。

我似乎無法弄清楚為什麼 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,我也有devstaging分支。典型的工作流程是創建一個分支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 腳本。

引用自:https://serverfault.com/questions/788131