[英]Is there a way to run a PHP script using Apache2's context right after its startup?
我有一個在 Raspberry Pi(Raspbian 11)內的 Apache2 上運行的服務器,php 8.0。
我目前正在編寫自己的服務器端mutex
php 模塊。 API 的想法是通過使用內置的 function: flock
來簡化多個請求之間全局互斥鎖的使用。
該模塊由 2 個函數組成: mutex_lock($name)
和mutex_unlock($name)
。 為簡單起見,我將僅解釋mutex_lock($name)
的概念。
在對全局變量進行一些研究后,我發現存儲在$GLOBALS
中的數據在會話之間持續存在。 因此,當客戶端 A在全局變量上加載資源時,相同的資源應該存在於客戶端 B 的請求中,因為A 的請求先於B 的請求。
現在,回到模塊。 我使用這個想法來存儲文件資源,因此多個 POST/GET 請求(也由 AJAX 發出)可以訪問相同的文件資源,從而訪問相同的互斥鎖 object 。
當mutex_lock($name)
被調用時:
$GLOBALS['mresources']
必須定義為關聯數組
檢查是否定義$GLOBALS['mresources'][$name]
:
2.1。 如果已定義,則使用此文件資源
2.2. 如果未定義,則存儲一個新的文件資源:
$file = fopen(path($name), "w+"); $GLOBALS['mresources'][$name] = $file;
應該調用flock($resource, LOCK_EX)
來鎖定文件資源,就像一個阻塞互斥鎖一樣。
從這個逐步指南中,我們已經可以得出一些問題:
我們如何才能真正確定$GLOBALS['mresources']
尚未定義? 在多線程環境中,當線程 A可能仍在檢查$GLOBALS['mresources']
的值是否為數組或它仍然為空時,另一個線程可能已經在該確切時間分配其值。 所以,這里的問題是線程 A 可以分配它的值 2x。 這樣, $GLOBALS['mresources']
可能會意外丟失存儲在其中的所有文件資源引用。
我們如何防止同樣的事情發生在這里: $GLOBALS['mresources'][$name] = $file;
? 如果客戶端 B檢查$GLOBALS['mresources']['log']
不存在,並且客戶端 C采取完全相同的操作和結果,我們如何同步訪問$GLOBALS['mresources']['log']
?
答案是:使用互斥鎖!
但問題是:我正在創建一個 API 來初始化互斥鎖,但我仍然被這個問題困擾。
我只是想創建一個全局互斥鎖來處理$GLOBALS['mresources']
上的訪問。 通過這種方式,我可以通過創建相同文件資源的副本來同步多個線程,並確保它們不會意外覆蓋其值。
但我只是不知道該怎么做。 我想在 Apache2 初始化其 PHP 實例之后以及在任何客戶端請求發出之前執行此腳本。 I've only found examples of running a separate PHP script, by modifying a bash script that Apache2 uses to start the Web Server. 但是這些實現在不同的進程上運行。
我想做的是調用一個腳本來在 Apache2 PHP 的上下文中定義一個文件資源,而不是運行不同的 PHP 進程。
有沒有辦法做到這一點?
我得到它。 全局變量不好。 但除此之外,有沒有辦法做到這一點?
在對全局變量進行一些研究后,我發現存儲在 $GLOBALS 中的數據在會話之間持續存在。
我建議你做更多的研究和現實生活中的測試,因為那根本不是真的。 PHP is often described as having a "shared nothing" model: every request starts with a completely clean environment, no data or even custom function and class definitions are carried across.
為了獲得任何“交叉請求”數據,您需要PHP 環境之外的東西,例如服務器上的共享 memory ......或文件系統上。
這讓我們回到了您鎖定文件的想法 - 您建議將 PHP 變量與(打開的)文件相關聯,然后鎖定它:
function mutex_lock(string $name): resource {
if ( ! isset($GLOBALS['mresources'][$name]) ) {
$file = fopen(path($name), "w+");
$GLOBALS['mresources'][$name] = $file;
}
$resource = $GLOBALS['mresources'][$name];
flock($resource, LOCK_EX);
return $resource;
}
但是鎖不會阻止其他進程/線程鎖定PHP 變量,它會阻止它們鎖定文件。 所以你實際上不需要“記住”進程之間的文件句柄——事實上,你不想這樣做,因為它是擁有鎖的,所以如果你共享它,你就是共享鎖,並且它不再是“排他的”。
因為文件名只是基於鎖名,實際上不需要記住任何東西,你可以完全刪除全局變量:
function mutex_lock(string $name): resource {
$resource = fopen(path($name), "w+");
flock($resource, LOCK_EX);
return $resource;
}
返回的資源本質上“是”鎖:讓它從 scope 中取出 go,它會自動關閉並解鎖文件; 或將其傳遞給fclose
以明確執行此操作。
然后,您只需要決定在無法獲取鎖時要發生什么,並且您擁有互斥鎖。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.