簡體   English   中英

有沒有辦法在啟動后立即使用 Apache2 的上下文運行 PHP 腳本?

[英]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)被調用時:

  1. $GLOBALS['mresources']必須定義為關聯數組

  2. 檢查是否定義$GLOBALS['mresources'][$name]

    2.1。 如果定義,則使用此文件資源

    2.2. 如果未定義,則存儲一個新的文件資源

     $file = fopen(path($name), "w+"); $GLOBALS['mresources'][$name] = $file;
  3. 應該調用flock($resource, LOCK_EX)來鎖定文件資源,就像一個阻塞互斥鎖一樣。

從這個逐步指南中,我們已經可以得出一些問題:

  1. 我們如何才能真正確定$GLOBALS['mresources']尚未定義? 在多線程環境中,當線程 A可能仍在檢查$GLOBALS['mresources']的值是否為數組或它仍然為空時,另一個線程可能已經在該確切時間分配其值。 所以,這里的問題是線程 A 可以分配它的值 2x。 這樣, $GLOBALS['mresources']可能會意外丟失存儲在其中的所有文件資源引用。

  2. 我們如何防止同樣的事情發生在這里: $GLOBALS['mresources'][$name] = $file; ? 如果客戶端 B檢查$GLOBALS['mresources']['log']不存在,並且客戶端 C采取完全相同的操作和結果,我們如何同步訪問$GLOBALS['mresources']['log']

答案是:使用互斥鎖!

但問題是:我正在創建一個 API 來初始化互斥鎖,但我仍然被這個問題困擾。


我想在 Apache2 開始運行后立即執行 PHP 腳本的原因:

我只是想創建一個全局互斥鎖來處理$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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM