2011-03-01 467 views
12

作爲應用程序日誌記錄的一部分,我試圖打開本地文件,如果該文件尚不存在,要創建一個新文件。下面是我有:PHP fopen()不創建文件,如果它不存在

$path = '/home/www/phpapp/logs/myawesome_logfile.txt'; 
$f = (file_exists($path))? fopen($path, "a+") : fopen($path, "w+"); 
fwrite($f, $msg); 
fclose($f); 
chmod($path, 0777); 

我再次檢查,而/logs目錄chmod爲0777,而我還跟它chown'ing到Apache的額外步驟:apache的好措施。儘管如此,當腳本打開文件時,它給了我一個警告,即文件不存在並且彈出。沒有文件被創建。

我是否需要禁止fopen()警告才能讓它創建文件?

+0

注意:如果'a +'無論出於何種原因追上我,我都會用'file_exists()'添加邏輯。 – 2011-03-01 21:10:28

+2

你真的想讓你的路徑從根開始嗎?這不會是你的應用的根目錄,那將是你係統的根目錄。 – 2011-03-01 21:11:14

+0

爲什麼你認爲錯誤抑制會幫助你打開一個文件? – 2011-03-01 21:28:57

回答

16

當您在PHP中使用路徑時,上下文可能很重要。如果您在重定向上下文中使用urls - 那麼根目錄('/')引用您的域的根目錄。鏈接文件或圖像的路徑以及include和require指令也是如此。

但是,當您處理文件系統命令(如fopen)時,根目錄('/')是系統根目錄。不是你的域根。

要解決此問題,請嘗試給出要從系統根目錄打開的日誌文件的完整路徑。例如:/var/www/phpapplication/logs/myLogFile.txt

或者您可以使用$_SERVER['DOCUMENT_ROOT'],如其他答案中所建議的那樣訪問服務器存儲的文件根目錄路徑的值。 /var/www部分。

編輯澄清。

+0

「當你處理文件處理命令如fopen()時,php從根目錄,而不是應用程序的根目錄。」呃...不,當你在路徑的開頭加上一個'/'就是從根目錄開始的。如果他把「phpapp/logs/myawesome_logfile.txt」從工作目錄中檢查,從上下文判斷這也是錯誤的。 – Powerlord 2011-03-01 21:31:02

+0

某些時候,將/ in放在前面會引導您訪問域的根目錄 - 例如使用url重定向。上下文決定我們是在討論根目錄還是根域。但是,由於路徑看起來相似,所以很容易混淆它們。 – 2011-03-01 21:33:56

+0

它正在獲得完整路徑。 (爲了簡潔起見,我在我的文章中刪除了/ home/www /部分路徑)。 – 2011-03-01 21:35:54

15

你試過嗎?

$msg = "I'm a line that is a message.\n"; 
$path = $_SERVER['DOCUMENT_ROOT'] . '/logs/myawesome_logfile.txt'; 
$f = fopen($path, "a+"); 
fwrite($f, $msg); 
fclose($f); 
chmod($path, 0777); 

您正在使用的服務器可能讓您只能在phpapp的目錄及其子目錄中工作。

+0

+1:DOCUMENT_ROOT幾乎肯定是這裏需要的修復程序。 – Powerlord 2011-03-01 21:30:37

1

您可以隨時打開文件,只需要"a",它也會創建一個新文件。
無需做出條件。

但是,你的代碼的主要問題是理解物理文件系統和虛擬網絡服務器之間的差異,這已經完全解釋了。

請注意,您應該提供您的問題與錯誤消息的確切副本。它包含了大量非常有用的信息,它不是一個誓言「我不會創建你的文件,走開!」但它是通過解釋什麼和爲什麼會出錯。如果你自己不關心這些有用的信息,你必須提供給那些尋求幫助的人。

+0

沒有涉及虛擬服務器,並且該腳本正在獲取該文件的完整路徑。我沒有這個方便的錯誤,但是當我能得到它時我會發布它。 – 2011-03-01 21:41:22

+0

@b。即hollenbeck,那麼錯誤信息會變得更加重要。 – 2011-03-01 21:43:50

0

文件的路徑必須在服務器根目錄下。我可以使用我想知道的文檔中的 phpinfo() 方法來實現此目的。所以當你使用phpinfo()時你會看到一個信息文檔。如果您發現 _SERVER [「SCRIPT_FILENAME」],您將看到文件的絕對路徑。

我希望這可以幫助別人。

0

不要忘記確保SELinux不會阻止你。

[根@ yourbox]#audit2allow < /var/log/audit/audit.log
#============= httpd_t ========= =====
#!!!!這avc可以允許使用布爾'httpd_unified' 允許httpd_t httpd_sys_content_t:dir {寫入add_name};
#!!!!這avc可以允許使用布爾'httpd_unified' 允許httpd_t httpd_sys_content_t:file {write create}; [根@ yourbox]#audit2allow -a -M my_httpd

注:

爲了使這一攬子政策積極,執行:

semodule -i my_httpd.pp

[root @ yourbox]#semodule -i my_httpd.pp
[root @ yourbox]#systemctl restart httpd

2

我在UBUNTU 14.04中解決了這個問題的一種方法是右鍵單擊文件所在的目錄並將「其他」權限更改爲「創建和刪除文件」。

相關問題