2026年4月11日 星期六

想修改 chcweb 出現的問題解決集

系列文章:
1.Ubuntu 24.04 安裝 chcweb 專案的過程記錄
2.Ubuntu 24.04 安裝 laravel 5.7 的過程記錄
3.laravel 5.7 初始相關設定與注意事項
4.想修改 chcweb 出現的問題解決集
 

問題一: UnexpectedValueException : The stream or file "/home/webadmin/html/chcweb/storage/logs/laravel-2026-04-11.log" could not be opened in append mode: failed to open stream: Permission denied

解決方法:
錯誤意思是 Laravel 沒辦法寫入 log 檔,通常跟 目錄權限 有關。 

1.檢查檔案與目錄權限

Laravel 日誌檔案路徑:

/home/webadmin/html/chcweb/storage/logs/laravel-2026-04-16.log

需要 Web 伺服器用戶能夠寫入。通常 Linux 系統 Web 伺服器用戶是:

  • Debian/Ubuntu:www-data
  • CentOS/Fedora:apachenginx

檢查目錄權限:

ls -l /home/webadmin/html/chcweb/storage/logs/

2.設定正確的擁有者

假設你的 Web 伺服器用戶是 www-data

sudo chown -R www-data:www-data /home/webadmin/html/chcweb/storage
這樣 Web 伺服器就能寫入。

3.設定正確的權限

Laravel 需要 storagebootstrap/cache 可寫:
sudo chmod -R 775 /home/webadmin/html/chcweb/storage
sudo chmod -R 775 /home/webadmin/html/chcweb/bootstrap/cache
  • 775:擁有者與群組可讀寫執行,其他人可讀與執行
  • 如果 775 仍然不行,可以暫時用 777 測試,但不建議長期使用(安全性較低) 

4.清除快取(可選)

Laravel 有時會快取檔案路徑,建議清除:

php artisan config:clear
php artisan cache:clear

然後再重新載入網站看看是否正常。

小技巧
Laravel 的 storagebootstrap/cache 目錄必須可寫,這是最常見的「Permission denied」原因。 

一行命令,直接安全地修復 Laravel 所有目錄的權限和擁有者,幾乎可以立即解決這種錯誤:

sudo chown -R www-data:www-data /home/webadmin/html/chcweb && sudo find /home/webadmin/html/chcweb/storage -type d -exec chmod 775 {} \; && sudo find /home/webadmin/html/chcweb/storage -type f -exec chmod 664 {} \; && sudo find /home/webadmin/html/chcweb/bootstrap/cache -type d -exec chmod 775 {} \; && sudo find /home/webadmin/html/chcweb/bootstrap/cache -type f -exec chmod 664 {} \; 

問題二:要在資料表setups 新增遺個欄位 bg_image

1.建立 Migration 

php artisan make:migration add_bg_image_to_setups_table --table=setups

2. 修改 Migration 檔案

<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddBgImageToSetupsTable extends Migration {
  public function up() {
      Schema::table('setups', function (Blueprint $table) {
          $table->string('bg_image', 255)->nullable()->after('bg_color')->comment('背景圖片');
      }); 
}

  public function down() {
       Schema::table('setups', function (Blueprint $table) {
          $table->dropColumn('bg_image');
       });
    }
}

3.執行 Migration

php artisan migrate 

問題三: UnexpectedValueException  : The stream or file "/home/webadmin/html/chcweb/storage/logs/laravel-2026-04-17.log" could not be opened in append mode: failed to open stream: Permission denied

問題解析:這個錯誤是 Laravel 在寫 log 檔案時發生的權限問題,完全跟你新增欄位無關,但它會阻止 migration 或任何程式寫入日誌。解決方式是調整 storagebootstrap/cache 的權限。

1.確認目錄

Laravel 需要以下目錄可讀寫:

  • storage
  • storage/logs
  • storage/framework
  • bootstrap/cache

 2.修改權限(Linux)

假設你的專案目錄是 /home/webadmin/html/chcweb

cd /home/webadmin/html/chcweb
# 設定 owner 為 web server 使用者,通常是 www-data (Ubuntu/Debian) 或 apache/nginx
sudo chown -R webadmin:www-data storage bootstrap/cache
# 設定目錄可寫權限
sudo chmod -R 775 storage bootstrap/cache
#注意:如果你的 web server 使用者不是 www-data,請改成實際使用者。

3.Laravel 快速清理快取(建議做)

php artisan config:clear
php artisan cache:clear
php artisan route:clear
php artisan view:clear

4. 測試

重新執行 migration:

php artisan migrate

如果權限設定正確,就不會再出現 Permission denied

💡小技巧

在開發環境中,設定 storagebootstrap/cache 777(所有人可寫)雖然方便,但生產環境建議限制為 775 或更安全的方式,以免安全風險。 

 6.一行指令
既改權限,又保證 Laravel 的 storagebootstrap/cache 可以被 web server 寫入,同時保持相對安全(775)

sudo chown -R webadmin:www-data /home/webadmin/html/chcweb/storage /home/webadmin/html/chcweb/bootstrap/cache && sudo chmod -R 775 /home/webadmin/html/chcweb/storage /home/webadmin/html/chcweb/bootstrap/cache 

問題四:   ErrorException  : file_put_contents(/home/webadmin/html/chcweb/database/migrations/2026_04_18_132842_add_bg_image_to_setups_table.php): failed to open stream: No such file or directory

問題解析:

這個錯誤訊息告訴我們 Laravel 無法寫入 migration 檔案,因為目標目錄不存在或沒有權限。重點在這兩件事:

  1. 目錄 database/migrations 是否存在
  2. 你的使用者是否有寫入權限

問題解答:

1.確認目錄存在

執行:

ls -ld /home/webadmin/html/chcweb/database/migrations
  • 如果出現 No such file or directory,表示這個目錄真的不存在,需要建立:
mkdir -p /home/webadmin/html/chcweb/database/migrations

2.確認權限

Laravel 需要該目錄可寫入:

sudo chown -R webadmin:www-data /home/webadmin/html/chcweb/database/migrations
sudo chmod -R 775 /home/webadmin/html/chcweb/database/migrations

替換 webadminwww-data 為你的實際使用者與 web server 群組。

3. 再次建立 migration

php artisan make:migration add_bg_image_to_setups_table --table=setups

這次 Laravel 就能成功在 database/migrations 產生檔案了。

💡 小提醒:

  • storagebootstrap/cachedatabase/migrations 都需要對 Laravel 可寫。
  • 開發環境可以用 775,生產環境更安全的做法是限制非必要使用者寫入。

 4. 一次性指令

把 Laravel 專案的 storagebootstrap/cachedatabase/migrations 全部權限一次調整好。

sudo mkdir -p /home/webadmin/html/chcweb/database/migrations && sudo chown -R webadmin:www-data /home/webadmin/html/chcweb/storage /home/webadmin/html/chcweb/bootstrap/cache /home/webadmin/html/chcweb/database/migrations && sudo chmod -R 775 /home/webadmin/html/chcweb/storage /home/webadmin/html/chcweb/bootstrap/cache /home/webadmin/html/chcweb/database/migrations

 

 

 

 

2026年2月21日 星期六

在LAMP + laravel 12 的虛擬機 ,輸入YT URL,就可下載YT 影片到自己電腦

        請參考 1.Ubuntu 24.04 安裝 laravel 12 的過程記錄,完成Ubuntu 24.04 + Apache2 + PHP 8.4 + Mariadb + Laravel 12 的相關設定。
        一、在 Ubuntu 24.04 安裝 yt-dlp:
        由於Ubuntu 24.04 內建套件通常偏舊,建議用官方 binary。
1.指令如下:
sudo apt update
sudo apt install ffmpeg -y
sudo curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o /usr/local/bin/yt-dlp
sudo chmod a+rx /usr/local/bin/yt-dlp
2.測試是否安裝成功,指令:
yt-dlp --version

        二、Laravel 設定
1.建立 YouTubeController.php
指令:php artisan make:controller 
YouTubeController  
內容:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Illuminate\Support\Str;

class YouTubeController extends Controller
{
public function showForm()
{
return view('youtube.form');
}

public function download(Request $request){
$request->validate([
'url' => 'required|url'
]);

$url = $request->input('url');

// 產生安全檔名
$filename = Str::uuid() . '.mp4';
$filePath = storage_path('app/downloads/' . $filename);

try {

$process = new Process([
'/usr/local/bin/yt-dlp', // 改成你實際路徑
'-f', 'mp4',
'-o', $filePath,
$url
]);

$process->setTimeout(300); // 最多跑 5 分鐘
$process->run();

if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}

return response()->download($filePath)->deleteFileAfterSend(true);

} catch (\Exception $e) {
return back()->with('error', '下載影片失敗: ' . $e->getMessage());
}
}
}

2.建立 form.blade.php
路徑:resources/views/youtube/form.blade.php
內容:

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>YouTube 影片下載</title>
</head>
<body>
<h1>下載 YouTube 影片</h1>

@if(session('error'))
<p style="color: red;">{{ session('error') }}</p>
@endif

<form action="{{ route('youtube.download') }}" method="POST">
@csrf
<label for="url">YouTube 影片網址:</label>
<input type="text" id="url" name="url" required>
<button type="submit">下載</button>
</form>
</body>
</html>

3.寫入 web.php
路徑:routes/web.php
內容:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\YouTubeController;

Route::get('/', function () {
return view('welcome');
});
Route::get('/youtube', [YouTubeController::class, 'showForm']);
Route::post('/youtube/download', [YouTubeController::class, 'download'])->name('youtube.download');


4.測試:http://Server IP/youtube




2026年2月8日 星期日

如何客製 WinPE 映像 - 新增驅動程式、更換背景圖、新增應用程式

系列文章:
1.如何用 ADK 製作 Windows PE 開機磁碟
2.如何客製 WinPE 映像 - 新增驅動程式、更換背景圖、新增應用程式

一、
用 ADK 製作 Windows PE 開機磁碟

4.在C:\ 建立資料夾WinPE,用來存放WinPE_x64.iso
mkdir C:\WinPE
copype amd64 C:\WinPE\WinPEx64
makewinpemedia /iso C:\WinPE\WinPEx64 C:\WinPE\WinPEx64.iso

二、以系統管理員身分開啟部署與映像工具環境

1.掛載映像檔指令: 
dism /Mount-Image /ImageFile:"C:\WinPE\WinPEx64\media\sources\boot.wim" /index:1 /MountDir:"C:\WinPE\WinPEx64\mount"

A.先說結論:一句話 這條指令的意思是: 把 boot.wim 裡的第 1 個 WinPE 映像掛載到指定資料夾,讓你可以修改 WinPE 的內容

B.各參數說明 dism Windows 內建的部署與映像管理工具 用來 掛載、修改、維護 Windows 映像檔(.wim、.vhd、.vhdx) /Mount-Image 告訴 DISM: =>把映像檔掛載成可存取的資料夾。掛載後,你可以像操作一般資料夾一樣: a.新增 / 刪除檔案、 b.加入驅動程式、 c.加入套件(cab / msu)、 d.調整設定。 /ImageFile:"C:\WinPE\WinPEx64\media\sources\boot.wim" 指定要掛載的 WIM 映像檔路徑:"C:\WinPE\WinPEx64\media\sources\boot.wim" boot.wim 是 WinPE 或 Windows 安裝環境 的映像檔, 在 WinPE 製作流程中,這就是「開機後跑的那個系統」。 /index:1 指定要掛載 WIM 裡的 第幾個映像。 一個 .wim 檔 可以包含多個映像, 例如: dism /Get-WimInfo /WimFile:boot.wim 可能看到: Index 1:Microsoft Windows PE Index 2:Microsoft Windows Setup 這裡的 /index:1 表示: =>掛載 第一個映像(通常是 WinPE 本體) /MountDir:"C:\WinPE\WinPEx64\mount" 指定 掛載後的資料夾:"C:\WinPE\WinPEx64\mount" 掛載完成後, C:\WinPE\WinPEx64\mount 就會變成一個「暫時展開的 WinPE 系統」。 你可以直接進去: Windows\System32 Program Files(如果有) 注意:這個資料夾: a.必須 事先存在、 b.必須是 空的資料夾。 2.新增驅動程式 dism /Image:"C:\WinPE\WinPEx64\mount" /Add-Driver /Driver:"C:\Drivers\Realtek\64\rt25cx21x64.inf"

A.先說結論:一句話 這條指令的意思是: 將 Realtek 驅動程式加入到已掛載的 WinPE 映像檔中。
B.各參數說明 dism Windows 內建的部署與映像管理工具 用來 掛載、修改、維護 Windows 映像檔(.wim、.vhd、.vhdx) /Image:"C:\WinPE\WinPEx64\mount"

指定已掛載的離線 Windows 映像目錄:"C:\WinPE\WinPEx64\mount"

/Add-Driver
新增驅動程式到映像檔

/Driver:"C:\Drivers\Realtek\64\rt25cx21x64.inf"
指定驅動程式的 .inf 檔案位置:"C:\Drivers\Realtek\64\rt25cx21x64.inf"

注意事項:
1.以「系統管理員身分」執行
2.確認 映像是否已掛載
    指令:dism /Get-MountedWimInfo
3.如果資料夾裡有多個驅動檔建議使用 /Recurse,讓 DISM 自動加入資料夾內所有 INF:
    指令:dism /Image:"C:\WinPE\WinPEx64\mount" /Add-Driver /Driver:"C:\Drivers\Realtek\64\rt25cx21x64.inf" /Recurse

3.列出映像內含的驅動程式(目的:檢查剛剛新增的驅動程式是否在內) dism /Image:"C:\WinPE\WinPEx64\mount" /Get-Drivers

A.先說結論:一句話 這條指令的意思是: 列出已掛載 WinPE 映像檔中的所有第三方驅動程式(不包含系統內建驅動)。
B.各參數說明 dism Windows 內建的部署與映像管理工具 用來 掛載、修改、維護 Windows 映像檔(.wim、.vhd、.vhdx) /Image:"C:\WinPE\WinPEx64\mount" 指定已掛載的離線 Windows 映像目錄:"C:\WinPE\WinPEx64\mount"
/Get-Drivers:
顯示目前映像內已安裝的驅動清單。

注意事項:
1.以「系統管理員身分」執行
2.確認 映像是否已掛載
    指令:dism /Get-MountedWimInfo
3.如果想看整齊資訊
    加上 /Format:Table 讓畫面更整齊:
    指令:dism /Image:"C:\WinPE\WinPEx64\mount" /Get-Drivers /Format:Table
4.如果想看詳細資訊
    加上 /All 會顯示包含內建驅動在內的所有驅動:
    指令:dism /Image:"C:\WinPE\WinPE_x64\mount" /Get-Drivers /All

4.儲存並且卸載 WinPE 映像 dism /Unmount-Image /MountDir:"C:\WinPE\WinPE_x64\mount" /Commit A.先說結論:一句話 這條指令的意思是: 把剛剛加入的驅動正式寫回 WIM 檔,並卸載映像檔。
B.各參數說明 dism Windows 內建的部署與映像管理工具 用來 掛載、修改、維護 Windows 映像檔(.wim、.vhd、.vhdx) /Unmount-Image 卸載已掛載的映像 /MountDir:"C:\WinPE\WinPE_x64\mount" 指定掛載目錄:C:\WinPE\WinPE_x64\mount"
/Commit 儲存變更 5. 創建 WinPE ISO 映像檔 makewinpemedia /iso C:\WinPE\WinPEx64 C:\WinPE\WinPE_custom.iso

A.先說結論: 這條指令的意思是:
將 C:\WinPE\WinPEx64 目錄中的 WinPE 建置內容,
製作成一個 ISO 映像檔,輸出為 C:\WinPE\WinPE_custom.iso
B.各參數說明
makewinpemedia
ADK 工具,用來產生:
a.開機 USB
b.開機 ISO

/iso
指定輸出格式為 ISO 映像檔,(另一個常用的是 /ufd,做 USB)

C:\WinPE\WinPEx64
來源資料夾,也就是 copype 建好的那個 WinPE 專案。

C:\WinPE\WinPEx64_custom.iso
輸出的 ISO 檔案路徑與名稱,完成後可以:
a.用虛擬機測試、
b.燒錄光碟、
c.丟進 PXE / iDRAC / iLO。


資料來源:
1.如何客製 WinPE 映像 - 新增驅動程式、更換背景圖、新增應用程式
2.Windows WIM映像入門#1 FFU映像 vs WIM映像,建立練習環境
3.Windows WIM映像入門#2 製作可開機的WinPE隨身碟或ISO
4.Windows WIM映像入門#3 sysprep初始化與建立WIM映像檔
5.Windows WIM映像入門#4 套用WIM映像檔
6.Windows FFU映像入門#5 套用FFU映像










如何用 ADK 製作 Windows PE 開機磁碟



如何使用 Microsoft Assessment and Deployment Kit (ADK) 製作 Windows PE (Windows 預先安裝環境) 開機媒體。
1.下載及安裝 Windows ADK:
        
取得
adksetup.exe 與 adkwinpesetup.exe

2.執行 adksetup.exe 

3.執行 adkwinpesetup.exe
4.在C:\ 建立資料夾WinPE,用來存放WinPE_x64.iso
mkdir C:\WinPE
copype amd64 C:\WinPE\WinPEx64
makewinpemedia /iso C:\WinPE\WinPEx64 C:\WinPE\WinPEx64.iso
三行合在一起的意思,整體流程一句話版:
1.建立WinPE 專案資料夾
2.建立 64 位元 WinPE 環境與 boot.wim
3.把WinPE 打包成可開機的 ISO


各指令解釋:
A.mkdir C:\WinPE 
Q:在做什麼?
=>建立一個資料夾:C:\WinPE
Q:用途?
=>當作 WinPE 專案的根目錄,
    之後 x64 / x86 / ARM64 的 WinPE 都可以放在這裡,
    純粹是準備資料夾,和 WinPE 本身還沒直接關係。

B.copype amd64 C:\WinPE\WinPEx64
Q:在做什麼?
=>使用 Windows ADK 的 copype 工具,
    建立一個 64 位元(x64 / amd64)WinPE 工作環境。

    參數拆解
    copype
    ADK 內建指令,
    用來「複製 + 初始化」WinPE 必要檔案。

    amd64
    指定架構
    代表 64 位元 x86(Intel / AMD)
    常見值:
    a.x86(32 位)
    b.amd64(64 位)
    c.arm64

    C:\WinPE\WinPEx64
    目標資料夾,
    copype 會在這裡建立完整結構。
    copype 產生的內容(重點),
    執行後會出現:
    C:\WinPE\WinPEx64\
    ├─ media\            ← 未來會變成 ISO / USB 的內容
    │  ├─ boot\
    │  ├─ efi\
    │  └─ sources\
    │     └─ boot.wim    ← WinPE 映像(超重要)
    
    ├─ fwfiles\
    └─ mount\            ← 之後掛載 boot.wim 用
    => boot.wim 就是你剛剛用 DISM 掛載的那個檔案。

C.makewinpemedia /iso C:\WinPE\WinPEx64 C:\WinPE\WinPEx64.iso
Q:在做什麼?
=>把剛剛準備好的 WinPE 專案,
    打包成一個可開機的 ISO 檔。

    參數拆解
    makewinpemedia
    ADK 工具,
    用來產生:
    a.開機 USB
    b.開機 ISO

    /iso
    指定輸出格式為 ISO 映像檔,
(另一個常用的是 /ufd,做 USB)

    C:\WinPE\WinPEx64
    來源資料夾,
    也就是 copype 建好的那個 WinPE 專案。

    C:\WinPE\WinPEx64.iso
    輸出的 ISO 檔案路徑與名稱,
    完成後你可以:
    a.用虛擬機測試、
    b.燒錄光碟、
    c.丟進 PXE / iDRAC / iLO。


資料來源:

只要點兩下,升級電腦後完成所有驅動程式的安裝

        最近電腦需要升級,需要將原先Windows 10 升級到Windows 11。過去,總是要依據原先主機的型號,到原廠官方網站。將驅動程式一個個下載好。等到windows升級完成,再將驅動程式一個個裝好。總覺得很累人,是否有方式能夠讓我只要點兩下,升級電腦後完成所有驅動程式的安裝

下載檔案解壓密碼:demo1234
使用步驟教學:


單機測試步驟:
1.下載檔案,解壓縮。解壓密碼:demo1234
2.匯出驅動設定檔->點選ExportDriverConf.bat
3.將桌面整個InstallDriver資料夾搬到隨身碟
4.升級Windows 11
5.將隨身碟內InstallDriver資料夾搬到桌面
6.匯入驅動設定檔->點選ImportDriverConf.bat

程式目的:匯出所有驅動設定檔inf 到所在的資料夾內的config
程式名稱:ExportDriverConf.bat
程式內容:
@echo off
REM ---------------以下是程式碼,不需更改---------------
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
if '%errorlevel%' NEQ '0' (
echo Requesting administrative privileges...
goto UACPrompt
) else ( goto gotAdmin )

:UACPrompt
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
exit /B

:gotAdmin
if exist "%temp%\getadmin.vbs" del "%temp%\getadmin.vbs"
pushd "%CD%"
CD /D "%~dp0"

echo ===============================
echo 正在匯出驅動程式(Dism)
echo 匯到:%~dp0config
echo ===============================

if not exist "%~dp0config" mkdir "%~dp0config"

dism /online /export-driver /destination:"%~dp0config"

echo 驅動匯出完成
pause
exit


程式目的:匯入config資料夾內所有驅動設定檔inf
程式名稱:ImportDriverConf.bat
程式內容:
@echo off

>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
if '%errorlevel%' NEQ '0' (
echo Requesting administrative privileges...
goto UACPrompt
) else ( goto gotAdmin )

:UACPrompt
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
exit /B

:gotAdmin
if exist "%temp%\getadmin.vbs" del "%temp%\getadmin.vbs"
CD /D "%~dp0"

echo ===============================
echo 正在匯入驅動程式(PnPUtil)
echo 來源:%~dp0config
echo ===============================

if not exist "%~dp0config" (
    echo 找不到 config 資料夾!
    pause
    exit
)

pnputil /add-driver "%~dp0config\*.inf" /subdirs /install

echo.
echo 驅動匯入完成
echo 建議重新開機
pause
exit

資料來源:
1.如何在 Windows 系統中將驅動程式匯入和匯出到另一台電腦









想修改 chcweb 出現的問題解決集

系列文章: 1. Ubuntu 24.04 安裝 chcweb 專案的過程記錄 2. Ubuntu 24.04 安裝 laravel 5.7 的過程記錄 3. laravel 5.7 初始相關設定與注意事項 4. 想修改 chcweb 出現的問題解決集   問題一: Unexpe...