關掉 PowerShell 的下載進度條換回下載速度

微軟的 Windows PowerShell 提供了許多的 Cmdlet、以及額外的模組,讓他的功能比傳統的命令提示字元(cmd)來的強大不少。

像是透過「Invoke-Webrequest」(官方文件),就可以直接透下載網路上的檔案,在很多情境下都是很實用的;他的基本使用方法大致上如下:

Invoke-Webrequest -Uri https://github.com/boostorg/boost/archive/refs/tags/boost-1.77.0.zip -OutFile c:tempboost.zip

但是如果有用這個指令來下載大型檔案的話,應該都會發現:他下載的速度真是有夠慢…

<!–more–>

像 Heresy 在這邊明明是在 1Gbps 的內網,但是下載一個不到 200MB 的檔案卻還要等好一陣子,下載速度也僅有不到 20Mbps(還沒有維持在高速…)

有的時候真的會下載到懷疑人生。

而後來才發現,這個問題原來是 PowerShell 為了顯示下載進度造成的。

在 WIndows PoerShell 使用「Invoke-Webrequest」來下載檔案的時候,他都會浮現一個藍底的對話框,告訴使用者當下已經完成多少資料了。

這種功能在使用者體驗上其實是好的。因為當下載時間久的時候,有狀態在更新,可以有效告訴使用者這個操作還活著、沒有掛掉。

試想,如果執行一個指令後,過個 10 秒、甚至更久的時間,什麼都沒變化,會覺得發生了什麼事呢?

但是問題是,「Invoke-Webrequest」這邊因為這個進度回報而拖延的時間實在太誇張了…

還好,PowerShell 也有提供參數,可以把這個進度關掉,讓下載速度大幅增加。

這邊要修改的,就是「$ProgressPreference」這個變數(官方文件);他的選項有下面四種:

  • Stop: 不顯示進度條、也不執行指令,會給一個錯誤訊息。
  • Inquire: 會在每次更新進度的時候跳出確認選項,詢問要怎麼處理。
  • Continue: 顯示進度條、並繼續執行。
  • SilentlyContinue: 不顯示進度條、並繼續執行。

他的預設值是「Continue」,而如果不想要看到進度條的話,則是要把它修改成「SilentlyContinue」;修改的指令很簡單,就是:

$ProgressPreference = 'SilentlyContinue'

修改這個參數再去下載的話,基本上就可以發揮網路的全部能力,快速地完成下載了!

Heresy 這邊也用「Measure-Command」(官方文件)來測試過,如果從 HiNet 的測速網站(連結)下載一個 100MB 的檔案,在有顯示進度的情況下,會花掉 85 秒左右。

而如果把進度關閉的話,則只需要 3 秒…這個差異已經接近 30 倍了…

下面就是測試的指令:

Measure-Command -Expression { Invoke-Webrequest http://http.speed.hinet.net/test_100m.zip }

這邊也要提醒一下,這個參數會影響到的 cmdlet 不只是「Invoke-Webrequest」;其他像是建立壓縮檔的「Compress-Archive」(官方文件)、或是解壓縮的「Expand-Archive」(官方文件)也同樣會受到影響。

而這類型的指令,在關閉進度條的顯示後,也都是會有相當程度的效能提升的!在 Heresy 這邊測試,壓縮檔案的速度在關閉進度條後快了 5 倍左右呢。

但是,如果把進度關掉的話,那執行指令後,就真的完全不知道當下到底進展到哪了。


另外,這個問題主要應該還是發生在 Windows 內建的 PowerShell 5.1 上。如果是在比較新版的 PowerShell Core 7(官方文件),儘管還是有類似形式的進度條,但是速度卻不會被大幅度拖慢,也不太需要這樣處理。

但是比較搞笑的是…好像還沒有什麼方法,可以把比較新的 PowerShell 7.x 設定成預設的 PowerShell、取代掉內建的 5.1 版。


參考:如何修正 PowerShell 執行龜速的元兇 (關閉進度列提示)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *