1. 程式人生 > 程式設計 >日誌檔案寫入失敗(permission denied)

日誌檔案寫入失敗(permission denied)

用過Laravel的小夥伴一開始安裝完框架後可能都遇到過daily 日誌檔案寫入失敗的問題,接下來我們就來詳細說下日誌檔案寫入失敗的原因以及對應的解決方案。

在講這個問題之前可能需要簡單介紹下Linux系統下的檔案的Ownership和Permission。

  • Ownership

  • User

    User是檔案的所有者,預設情況下,使用者建立了一個檔案,該檔案的所有者就是該使用者。

  • Group

    一個使用者組能包含多個使用者,所有屬於這個組的使用者都有相同的許可權來訪問檔案。假設你有一個專案,很多使用者都需要訪問這個專案檔案的許可權,你不需要手動賦予這些使用者所有許可權,你只需要把這些使用者加到一個組裡面,賦予這些組有訪問檔案的許可權,這樣一來就僅僅只有組裡面的成員能對檔案進行讀寫操作。

  • Other

    任何其他的使用者都能訪問檔案,因此,給Other使用者賦予許可權,相當於所有使用者都擁有這個許可權。

  • Permission

    在 UNIX/Linux 系統中每一個檔案和目錄都有3中許可權,以下就是對三個所有者的討論。

    • Read: 這個許可權賦予你開啟和讀取檔案的許可權。擁有目錄的讀許可權,你能列出其內容。
    • Write: 擁有了讀許可權,你能修改檔案的內容。擁有了目錄的寫許可權,你能新增、移除以及重新命名該目錄下的檔案。考慮一種場景,當你擁有檔案的寫許可權,但是沒有檔案儲存目錄的寫許可權,你還是能修改檔案的內容,但不能重新命名、移動以及移除目錄下的檔案。
    • Execute:
      在Windows系統中,一個可執行的程式通常都有.exe字尾,你能很方便的執行它。在 UNIX/Linux 中,除非被賦予可執行許可權,否則你將不能執行該程式。如果未授權可執行許可權,你讓然可以看並修改程式程式碼(被授予讀和寫許可權),但是無法執行它。

linux下檔案資訊的顯示截圖

linux下目錄的資訊顯示截圖

以上的截圖顯示了一個檔案和資料夾的資訊,我們可以看到:

  • r 代表可讀, w 代表可寫, x 代表可執行。
  • 第一位檔案顯示 - ,檔案顯示 d
  • 上面第一張圖片, rw-rw-r-— 中。第一組 rw- 表示檔案的所有者對檔案有可讀、可寫、不可執行的許可權。第二組 rw-
    表示檔案所屬的組內使用者對該檔案有可讀、可寫、不可執行的許可權。第三組 r-— 表示其他任何使用者對該檔案有可讀、不可寫、不可執行的許可權。
  • rw-rw-r-- 用二進位製表示為 664 ,每一位如有許可權則為 1 ,否則為 0 ,第一個三位 rw- 用二進位製表示為 110 轉化為十進位制就是 6,後面兩組依次類推,最後得到 664
  • 上面第一張圖片的 dior www-data 表示該檔案的所有者是 dior 使用者,檔案屬於 www-data 組。

我們知道很多應用系統中的日誌是寫檔案的,且是以日期來命名檔案的。所以第一次建立日誌的使用者就顯得尤為重要,如果檔案建立的 OnwerGroup 不對,其他的使用者觸發寫入日誌檔案就會失敗。

接下來我們討論下有多少種不同的使用者可能建立日誌檔案:

  • Crontab中執行的定時任務,跟建立 Crontab 的使用者有關,此時建立的檔案 OwnerGroup 值分別是該使用者以及預設的 Group
  • 一些常駐的後臺程式,比如Laravel中的 queue work ,此時建立的日誌檔案 OwnerGroup 值分別是執行該程式的使用者以及所屬的預設 Group
  • 正常使用者訪問網站產生的日誌檔案,此時建立的日誌檔案的 OwnerGroup 都是 www-datawww-data 使用者是web伺服器預設的使用者。

由以上的分析,我們大概已經找到了解決問題的方法。

  • 執行使用者建立日誌檔案的許可權為 664 比較恰當,這就需要當前使用者的umask為 0002
  • 當前執行使用者的預設 Group 應該設定為 www-data

下面就說下我的具體解決方案:

指定www-data使用者執行crontab:

sudo crontab -u www-data -e
複製程式碼

Laravel中修改建立日誌檔案的許可權:

編輯 confog/logging.php 檔案

新增 'permission' => 0664

'daily' => [
		'driver' => 'daily','path' => storage_path('logs/laravel.log'),'level' => 'debug','days' => 14,'permission' => 0664,],複製程式碼

你有什麼更好的方法麼?歡迎留言!