Git Bash中SYSTEM用戶的HOME目錄、SSH以及自動化部署的WebHooks問題

問題的產生

有個項目php網站部署的服務器時Windows Server環境(不要問我爲什麼....),php運行於openresty-nginx,代碼託管與gitee.com。網站自動部署方案爲:gitee.com上爲項目配置部署的公鑰和WebHooks,網站中的php頁面響應gitee.com下的鉤子,然後調用exec執行"git pull"。

但是不知道哪一天,這個自動化部署方案突然崩了.....,跟蹤了一下php頁面中“git pull”的結果,居然無權限訪問遠程倉庫:

fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

奇怪,之前一直正常的過程,爲什麼突然git沒權限了?

分析與驗證

仔細回想,服務器的nginx剛剛替換成了openresty-nginxj,再仔細檢查,nginx進程和php進程的用戶,是SYSTEM,不是Administrator。而Git Bash默認的用戶是Administrator,默認的ssh配置也僅Administrator有。也就是說,php中exec 執行“git pull”時,是沒有ssh祕鑰配置的另一個用戶:SYSTEM。

爲了驗證這個猜想,我在php中exec調用"whoami",檢查輸出結果,不出所料,輸出了:

nt authority\system

通過在php中exec調用"cd ~ && pwd",找到了SYSTEM用戶的HOME目錄:"C:\Windows\System32\config\systemprofile"

再檢查system用戶有沒有默認的.ssh目錄以及祕鑰文件,果然沒有。

最後

爲system用戶配置全套的ssh祕鑰,並在gitee.com上重新配置部署公鑰,問題得到解決。

附上php端響應gitee.com鉤子實現自動拉取的代碼(部分參考了:https://gist.github.com/ada10fl2/9118419):

<html>
	<head>
	</head>
	<body>
<?php
$header = get_all_header(); //獲取頭信息
$json = json_decode(file_get_contents('php://input'), true); //解析json
$filename = "logs/log".date("Ymdhis").".txt";

$resp_name = "prj";                // 替換成你自己的倉庫名稱
$branch = "refs/heads/release";    // 替換成你想要拉取的分支名稱

//驗證信息是否正確
if (strcmp($header["user-agent"], "git-oschina-hook")==0 &&
	strcmp($json["hook_name"], "push_hooks")==0 &&
	strcmp($json["repository"]["name"], $resp_name)==0 &&
	strcmp($json["ref"], $branch) == 0)
{		
	// 下面這些路徑,請根據你自己的安裝位置修改
	$l_git = "/d/Program Files/Git/bin/git.exe";
	$l_sshadd = "/d/Program Files/Git/usr/bin/ssh-add.exe";

	$w_agent = "D:\\Program Files\\Git\\usr\\bin\\ssh-agent.exe";	
	$w_bash =  "D:\\Program Files\\Git\\bin\\bash.exe";

	$l_cmd = "'\"$l_sshadd\" /path/to/your/rsa; "
		. "\"$l_git\" pull'";
		
	$exec = "\"$w_agent\" \"$w_bash\" -c $l_cmd 2>&1";
	
	echo "Runnning...\n<br>";
	$t0 = microtime(true);
	echo "<pre>$exec</pre>";
	$logs = shell_exec($exec);
	echo ($logs);
	$t = round(microtime(true) - $t0,3)*1000;
	echo "<br>Done: $t ms";

	//輸出git結果到log.txt
	file_put_contents($filename, "\n[git output]\r\n ".$logs."\n");
}
else
{
	$logs = "user-agent:" . $header["user-agent"] . "\r\n";
	$logs = $logs . "hook_name:" . $json["hook_name"] . "\r\n";
	$logs = $logs . "repository name:" . $json["repository"]["name"] . "\r\n";
	$logs = $logs . "branch name:" . $json["ref"] . "\r\n";
	file_put_contents($filename, "\n[log]\r\n".$logs."\n");
	echo ($logs);
}
http_response_code(200);;
exit("");

function get_all_header()
{
	$ignore = array('host','accept','content-length','content-type');
	$headers = array();
	foreach($_SERVER as $key=>$value)
	{
		if (substr($key, 0, 5)==='HTTP_')
		{
			$key = substr($key, 5);			
			$key = str_replace('_', ' ', $key);
			$key = str_replace(' ', '-', $key);

			$key = strtolower($key);
			if(!in_array($key, $ignore)){
			  $headers[$key] = $value;
			}			
		}
	}
	return $headers;
}
?>

	</body>
</html>

代碼比較粗糙,大家有好的改進可以貼在下面👇,謝謝😁。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章