# Laravel 解決在 CentOS 7 下 log 檔無法寫入的問題

在 `config/logging.php`

'permission' =&gt; 0775,

```JSON
'daily' => [
        'driver' => 'daily',
        'path' => storage_path('logs/laravel.log'),
        'level' => 'debug',
        'days' => 7,
        'permission' => 0775,
    ],
```

---

在非 homestead 的主機上執行 laravel 時，有時會出現空白畫面，或是以下的錯誤訊息：

```
The stream or file "/xxxx/yyyy/zzzz/storage/logs/laravel-<日期>.log" could not be opened: failed to open stream: Permission denied
```

這是因為我們使用不同的方式執行 laravel 程式，會讓 log 檔有不同權限設定，和沒有檔案的寫入權限。

內容目錄

<div id="bkmrk-%E8%A7%A3%E6%B3%95%E4%B8%80%EF%BC%9A%E5%B0%87-logs-%E7%9B%AE%E9%8C%84%E5%8F%8A%E6%AA%94%E6%A1%88%E6%AC%8A%E9%99%90%E7%9B%B4%E6%8E%A5"><div></div><nav>- [解法一：將 logS 目錄及檔案權限直接設為 777 (不推薦)](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E8%A7%A3%E6%B3%95%E4%B8%80%EF%BC%9A%E5%B0%87_logS_%E7%9B%AE%E9%8C%84%E5%8F%8A%E6%AA%94%E6%A1%88%E6%AC%8A%E9%99%90%E7%9B%B4%E6%8E%A5%E8%A8%AD%E7%82%BA_777_(%E4%B8%8D%E6%8E%A8%E8%96%A6) "解法一：將 logS 目錄及檔案權限直接設為 777 (不推薦)")
- [解法二：設計好適當的權限](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E8%A7%A3%E6%B3%95%E4%BA%8C%EF%BC%9A%E8%A8%AD%E8%A8%88%E5%A5%BD%E9%81%A9%E7%95%B6%E7%9A%84%E6%AC%8A%E9%99%90 "解法二：設計好適當的權限")
    - [步驟一：設定群組權限](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E6%AD%A5%E9%A9%9F%E4%B8%80%EF%BC%9A%E8%A8%AD%E5%AE%9A%E7%BE%A4%E7%B5%84%E6%AC%8A%E9%99%90 "步驟一：設定群組權限")
    - [步驟二：修改「網頁伺服器」的預設檔案存取權限](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E6%AD%A5%E9%A9%9F%E4%BA%8C%EF%BC%9A%E4%BF%AE%E6%94%B9%E3%80%8C%E7%B6%B2%E9%A0%81%E4%BC%BA%E6%9C%8D%E5%99%A8%E3%80%8D%E7%9A%84%E9%A0%90%E8%A8%AD%E6%AA%94%E6%A1%88%E5%AD%98%E5%8F%96%E6%AC%8A%E9%99%90 "步驟二：修改「網頁伺服器」的預設檔案存取權限")
    - [步驟三、修改「命令列」的預設檔案存取權限](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E6%AD%A5%E9%A9%9F%E4%B8%89%E3%80%81%E4%BF%AE%E6%94%B9%E3%80%8C%E5%91%BD%E4%BB%A4%E5%88%97%E3%80%8D%E7%9A%84%E9%A0%90%E8%A8%AD%E6%AA%94%E6%A1%88%E5%AD%98%E5%8F%96%E6%AC%8A%E9%99%90 "步驟三、修改「命令列」的預設檔案存取權限")
    - [步驟四、修改 「cron」 的預設檔案存取權限](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E6%AD%A5%E9%A9%9F%E5%9B%9B%E3%80%81%E4%BF%AE%E6%94%B9_%E3%80%8Ccron%E3%80%8D_%E7%9A%84%E9%A0%90%E8%A8%AD%E6%AA%94%E6%A1%88%E5%AD%98%E5%8F%96%E6%AC%8A%E9%99%90 "步驟四、修改 「cron」 的預設檔案存取權限")
    - [解法二總結](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E8%A7%A3%E6%B3%95%E4%BA%8C%E7%B8%BD%E7%B5%90 "解法二總結")
- [參考資料](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E5%8F%83%E8%80%83%E8%B3%87%E6%96%99 "參考資料")

</nav></div>## <span class="ez-toc-section" id="bkmrk--0"></span>解法一：將 logS 目錄及檔案權限直接設為 777 (不推薦)

<div id="bkmrk-chmod--r-777-storage">```php
chmod <span class="token operator">-</span>R <span class="token number">777</span> storage<span class="token operator">/</span>logs<span class="token operator">/</span>
```

<div><div>PHP</div></div></div>**這方法最快，但是只能治標，不能治本，有再度發生的可能；而且，還有安全性的隱憂**

## <span class="ez-toc-section" id="bkmrk--1"></span>解法二：設計好適當的權限

以 CentOS 為例，在 CentOS 中，我們以 apache 的 virtual host 來執行我們的 laravel 系統，會有三個比較常見的狀況：  
一、透過「網頁伺服器」執行程式  
二、透過「命令列」執行程式  
三、透過 「cron」 執行程式  
各會有不同的檔案權限規則應用在新產生的檔案。我們必須針對這三種方式，來規劃不同的權限規則。

### <span class="ez-toc-section" id="bkmrk--2"></span>步驟一：設定群組權限

由於 網頁伺服器的預設執行帳號是 apache，所以其產生的檔案，owner及group 均是 apache；而命令列或 cron，則會根據登入的使用者帳號來設定，為了要讓不同方式產生的檔案，能透過「群組權限」的設定值來存取程式，我們必需做一些設定，假設我們 virtual host 的網頁檔案是以 john 這個帳號來登入的

<div id="bkmrk-%23-%E6%8A%8A-john-%E5%8A%A0%E5%85%A5-apache-%E7%BE%A4">```bash
<span class="token comment"># 把 john 加入 apache 群組</span>
<span class="token function">usermod</span> -a -G apeche john
<span class="token comment"># 也把 apache 加入 john 群組</span>
<span class="token function">usermod</span> -a -G john apache
```

<div><div>Bash</div></div></div>**更改群組後，shell 要重新登入；部分服務需重新開機才能套用群組權限設定**

如果對於 Linux 的檔案權限不太熟悉，可以看一下[鳥哥的文章 - Linux 檔案與目錄管理](http://linux.vbird.org/linux_basic/0220filemanager.php#umask "鳥哥的文章 - Linux 檔案與目錄管理")。

### <span class="ez-toc-section" id="bkmrk--3"></span>步驟二：修改「網頁伺服器」的預設檔案存取權限

apache server 預設的執行帳號是 apache，產生的檔案權限為 644，範例如下：

```
-rw-r--r-- 1 apache apache    153438 12月 24 20:49 laravel-2019-12-24.log

```

我們必須設定 apache 的 umask 設定，讓其產生的檔案權限為 664，這樣一來，apache 群組才具有寫入的權限。

**設定檔 umask.conf 內容**

```
[Service]
UMask=0002
```

指令如下：

<div id="bkmrk-mkdir-%2Fetc%2Fsystemd%2Fs">```bash
<span class="token function">mkdir</span> /etc/systemd/system/httpd.service.d
<span class="token function">vi</span> /etc/systemd/system/httpd.service.d/umask.conf

systemctl daemon-reload
systemctl restart httpd.service
```

<div><div>Bash</div></div></div>### <span class="ez-toc-section" id="bkmrk--4"></span>步驟三、修改「命令列」的預設檔案存取權限

有時我們會透過 php artisan 來執行程式，產生的檔案, 其使用者和群組就是登入的帳號，而權限會根據 umask 來決定其權限。

<div id="bkmrk-%23-%E5%9C%A8-shell-%E4%B8%AD%EF%BC%8C%E7%9B%B4%E6%8E%A5%E8%BC%B8%E5%85%A5-uma">```bash
<span class="token comment"># 在 shell 中，直接輸入 umask 可以查看目前設定</span>
<span class="token function">umask</span>

<span class="token comment"># 修改 umask 為 0002</span>
<span class="token function">umask</span> 0002

<span class="token comment"># 將 umask 0002 的設定加入登入設定檔</span>
<span class="token function">vi</span> ~/.bashrc

```

<div><div>Bash</div></div></div>### <span class="ez-toc-section" id="bkmrk--5"></span>步驟四、修改 「cron」 的預設檔案存取權限

當透過 cron 來進行工作排程時，其所產生的檔案，owner 和 group 是登入帳號，預設的 umask 是，0022，我們可以透過修改設定檔來改變：

<div id="bkmrk-%23-%E4%BF%AE%E6%94%B9%E8%A8%AD%E5%AE%9A%E6%AA%94%EF%BC%8C%E5%9C%A8%5Bservice%5D-%E6%AE%B5">```bash
<span class="token comment"># 修改設定檔，在[Service] 段中，加入 UMask=0002</span>
<span class="token function">vi</span> /usr/lib/systemd/system/crond.service

systemctl daemon-reload
systemctl restart crond.service
```

<div><div>Bash</div></div></div>重新啟動 cron 服務後，其所產生的檔案權限就會變為 664

### <span class="ez-toc-section" id="bkmrk--6"></span>解法二總結

解法二的處理方式是要達到 2 個目標  
1、三種執行方式所產生的 log 檔案，不管 owner 是 apache 或是 john，其權限都是 664  
2、apache 和 john 這兩個帳號，都加入對方的群組中

來源：[https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/)