【QPKG】sherpa:迷你套件管理器(命令列介面)


sherpa:QNAP NAS 的迷你套件管理器

全球首款多動作 CLI 套件管理器!

透過 sherpa 進行套件管理,提供如輕鬆備份應用程式、升級、服務與守護程序管理、多執行緒操作、自我檢查與修復等功能,所有操作都可透過 cron 自動化。

重要提醒: 這是一個命令列套件與服務管理器,目前處於 beta 階段,套件有可能因自動升級失敗而損壞。如果您願意(且能夠)協助診斷並提供日誌,且不介意偶爾出現問題,請使用此套件。如果您追求完全穩定、希望「安裝即忘」的解決方案,目前還無法在這裡實現。請勿在生產環境中使用 sherpa,除非您熟悉 CLI 並能除錯 bash 與 Python 腳本,或可以接受應用程式長時間無法運作。

話雖如此:目前大部分開發已完成,現正致力於提升自動套件升級時的穩定性。因此,sherpa 在全新(或新安裝)系統上運作良好,但在個別應用程式更新時可能會遇到問題。

點此查看可安裝套件

安裝方式

  • SSH 登入您的 NAS,並在命令列手動安裝 QPKG:
    curl -skL https://tinyurl.com/get-sherpa > /share/Public/sherpa.qpkg; sudo sh /share/Public/sherpa.qpkg;

使用方式

  • 在命令列執行:
    sudo sherpa
    …然後依照說明操作。

    如果您的 QTS 版本無法使用 ‘sudo’,請以 ‘admin’ 使用者透過 SSH 登入 NAS,並執行:
    sherpa

如果您有建議、意見、評論或疑慮,請建立新的 issue,或歡迎開啟新的 討論 主題。

本專案是社群共同努力的成果,並結合了許多 QNAP 社群論壇成員的回饋。感謝所有貢獻者。:nerd_face:

更多資訊請參閱 wiki:https://github.com/OneCDOnly/sherpa/wiki

對於 Readarr 用戶來說,有些不幸的消息:開發者已停止開發,現有的分支(sherpa 使用的分支)也已被封存:https://www.reddit.com/r/Readarr/comments/1llqji9/announcement_retirement_of_readarr

如果有人知道有在維護的分支,請告知,我會將 Readarr QPKG 切換至該分支。若沒有,Readarr QPKG 仍會繼續提供,但不會再有任何升級。

更多壞消息:TorrServer 的開發者現在編譯的二進位檔需要 libc 2.34,而 QTS 尚未提供此版本。:disappointed:

所以,目前 TorrServer 套件無法運行。現有的 TorrServer 使用者在下次 TorrServer 更新時會發現安裝已損壞,且 TorrServer 將在下一個穩定 QPKG 版本中從 sherpa 支援列表移除。

如果你想繼續使用這個應用程式,可以在 myQNAP 儲存庫找到舊版本:https://www.myqnap.org/product/torrserver/

你可能可以將現有的設定檔轉移過去。但在安裝 myQNAP 版本前,請務必手動備份你的設定檔。

你的 sherpa 版 TorrServer 應該透過 QTS App Center 手動解除安裝。

Hi OneCD,希望你一切安好?

在最新的 Sherpa 更新後,我在 SickGear 上遇到以下錯誤。

Error
OverflowError('date value out of range')

Traceback
Traceback (most recent call last):
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/tornado/web.py", line 1848, in _execute result = await result ^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/tornado/gen.py", line 796, in run yielded = self.gen.throw(exc) ^^^^^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/sickgear/webserve.py", line 1044, in get yield self.route_method(route, use_404=True)
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/tornado/gen.py", line 783, in run value = future.result() ^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/tornado/gen.py", line 796, in run yielded = self.gen.throw(exc) ^^^^^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/sickgear/webserve.py", line 350, in route_method result = yield self.async_call(method, filter_kwargs) # method(**filter_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/tornado/gen.py", line 783, in run value = future.result() ^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/sg_futures/py3.py", line 40, in run result = self.fn(*self.args, **self.kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/sickgear/webserve.py", line 359, in async_call raise e
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/sickgear/webserve.py", line 357, in async_call return function(**kw) ^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/sickgear/webserve.py", line 1148, in view_shows return Home(self.application, self.request).view_shows() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/sickgear/webserve.py", line 1758, in view_shows return t.respond() ^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/config/cache/cheetah/_share_CACHEDEV1_DATA__qpkg_OSickGear_repo_cache_gui_slick_interfaces_default_home_tmpl.py", line 441, in respond data_lastdate = VFN(VFN(VFFSL(SL,"SGDatetime",True),"convert_to_setting",False)(VFN(VFFSL(SL,"network_timezones",True),"parse_date_time",False)(VFFSL(SL,"cur_airs_last",True), VFFSL(SL,"cur_show_obj.airs",True), VFFSL(SL,"cur_show_obj.network",True))),"strftime",False)('%Y%m%d%H%M') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/dateutil/tz/tz.py", line 231, in dst if self._isdst(dt): ^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/dateutil/tz/tz.py", line 294, in _isdst if self.is_ambiguous(dt): ^^^^^^^^^^^^^^^^^^^^^
File "/share/CACHEDEV1_DATA/.qpkg/OSickGear/repo-cache/lib/dateutil/tz/tz.py", line 256, in is_ambiguous (naive_dst != self._naive_is_dst(dt - self._dst_saved))) ~~~^~~~~~~~~~~~~~~~~
OverflowError: date value out of range

Request Info
method: GET
uri: /view-shows/
version: HTTP/1.1
headers:
body: b''
remote_ip: xxxxxxxxxxxxxxx
protocol: http
host: xxxxxxxxxxxxxxxxxxx
host_name: xxxxxxxxxxxxxxxxxxx
files: {}
connection:
server_connection:
_start_time: 1758182428.793617
_finish_time: None
path: /view-shows/
query:
arguments: {}
query_arguments: {}
body_arguments: {}
_cookies:

我已經嘗試重新啟動和重新安裝,但還是出現同樣的錯誤。有什麼建議嗎?

嗨 Shady,歡迎來到新論壇。:slight_smile:

請你先執行一下 check 動作嗎?

sherpa check

sherpa check
sherpa v250822-stable
完成:動作已完成。

• 套件動作開始於 10:20:15 AM,結束於 10:20:41 AM,耗時 = 26 秒

• 以下套件動作已成功完成:
3 秒內安裝輔助 PIP
1 秒內重新啟用 nzbToMedia QPKG
16 秒內重新啟用 OSickGear QPKG
17 秒內重新啟用 SABnzbd QPKG

• 以下套件動作已跳過(原因如下):
1 秒內「簽署」Entware QPKG(已簽署)
1 秒內「簽署」Par2 QPKG(NAS 架構不相容)
1 秒內「簽署」Par2turbo QPKG(已簽署)
1 秒內「簽署」sherpa QPKG(已簽署)
1 秒內「簽署」SortMyQPKGs QPKG(QTS 版本不相容)
1 秒內「簽署」Unrar QPKG(已簽署)
1 秒內「簽署」nzbToMedia QPKG(已簽署)
1 秒內「簽署」SABnzbd QPKG(已簽署)
1 秒內「簽署」OSickGear QPKG(已簽署)
1 秒內重新啟用 ClamAV QPKG(未安裝)

到目前為止看起來不錯。:+1:

接下來:請對 SickGear 執行一次 clean 動作:

/etc/init.d/sickgear.sh clean

…然後嘗試 start 它:

/etc/init.d/sickgear.sh start debug
[~] # /etc/init.d/sickgear.sh clean
> 來源:sickgear.sh,動作:clean,時間:2025年9月18日 週四 上午10:56:11 BST,負載:0.20 
- 套件:250822,服務:250822,函式庫:250822
> QPKG 啟用:true
> 應用程式自動更新:true
- 目前 git 分支:main
- 守護程序 PID:11350
> 使用 SIGTERM 停止守護程序 PID 11350(不超過120秒):1, 2, OK
- 守護程序 PID:無
> 清理本地儲存庫:OK
> 清理虛擬 Python 環境:OK
> 清理 PyPI 快取:OK
> 清理暫存路徑:OK
- 檔案存在:/opt/bin/git
> 從遠端儲存庫建立 'OSickGear':OK
- 目前 git 分支:main
> 建立新的虛擬 Python 環境:OK
> 建立 QPKG 'pip' 設定:OK
> 新增位置 '/share/CACHEDEV1_DATA/.qpkg/OSickGear/pip-cache' 為 'pip' 快取:OK
> 新增位置 '/share/CACHEDEV1_DATA/.qpkg/OSickGear/qpkg-wheels' 至 'pip' 搜尋路徑:OK
> 從 pip-requirements.txt 排除有問題的 PyPI 模組:OK
> 從 pip-recommended.txt 排除有問題的 PyPI 模組:OK
> 從 pip-requirements.txt 安裝 PyPI 模組:OK
> 從 pip-recommended.txt 安裝 PyPI 模組:OK
> 從設定檔載入埠口:OK
> 啟動守護程序:OK
> 監控守護程序進程名稱出現(不超過120秒):1, OK
> 等待10秒確認 PID 仍存活:1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 完成
- 守護程序 PID:8916
- 守護程序監聽位址:0.0.0.0
> 啟用 HTTPS 埠口:false
- HTTP 埠口:7181
> 測試埠口 7181 回應(不超過120秒):OK
> 以 UI 埠口更新 QPKG 圖示:OK
= 來源:sickgear.sh,動作:clean,時間:2025年9月18日 週四 上午10:56:36 BST,結果:OK,耗時:0小時:00分:26秒,負載:0.45 
[~] # /etc/init.d/sickgear.sh start debug
> 來源:sickgear.sh,動作:start,時間:2025年9月18日 週四 上午10:56:56 BST,負載:0.32 
- 套件:250822,服務:250822,函式庫:250822
> QPKG 啟用:true
> 應用程式自動更新:true
- 目前 git 分支:main
- 守護程序 PID:8916
= 來源:sickgear.sh,動作:start,時間:2025年9月18日 週四 上午10:56:56 BST,結果:OK,耗時:23毫秒,負載:0.32 

已經執行了。仍然顯示錯誤

Clean 看起來不錯,啟動也沒問題(事實上,看起來 SickGear 伺服程式已經在運行了)。:+1:

你是在哪裡看到那個錯誤的?

http://xxxxxxxxxxxxx:7181/view-shows

我可以正常登入,但在進入節目頁面時出現錯誤。

你有強制重新整理你的網頁嗎?請按 CTRL-F5。

是的,還是沒有結果

嗯,我在想是否有無效的值被寫入了 SickGear 資料庫?

為了測試,我們來嘗試用全新的資料庫啟動 SickGear。我們會先備份你現有的資料庫,之後再還原。這不是修復方法——只是測試而已。

要備份你目前的資料庫檔案:

/etc/init.d/sickgear.sh backup

……然後將 SickGear 設定重置為預設值:

/etc/init.d/sickgear.sh reset-config

現在,請再次嘗試存取你的 SickGear 網頁。你的影集清單會是空的。有顯示任何錯誤嗎?

測試完之後,請用以下指令還原你的 SickGear 資料庫檔案:

/etc/init.d/sickgear.sh restore

SickGear 會自動根據需要停止和啟動。這次不需要貼上任何輸出。

我試過了,兄弟,還是沒用。錯誤訊息依然一樣。

請確認:您是在重置設定後、恢復設定之前嘗試存取 SickGear 網頁嗎?並且看到相同的錯誤?

這個問題可能需要 SickGear 開發人員的協助:[How to] Report Issues · SickGear/SickGear Wiki · GitHub

另外也有「官方」的 SickGear 套件可以使用,或許可以嘗試看看?Install SickGear 05 QNAP · SickGear/SickGear Wiki · GitHub

好吧,我作弊了。我用 Claude 來解碼這個錯誤 :slight_smile:

SickGear 日期溢出錯誤 - 問題摘要與修復

問題說明:

SickGear 在嘗試載入 view-shows 頁面時出現了 OverflowError('date value out of range')(日期值超出範圍溢出錯誤)。該錯誤發生在處理節目播出日期進行時區計算時。

根本原因:

SickGear 資料庫中包含了來自 1970 年(大約 1970 年 1 月 9 日)的時間戳記,而不是正確的近期日期:

  • 節目(Shows)last_update_indexer 的值約為 739435(對應 1970-01-09)
  • 集數(Episodes)airdate 的值約為 738153-738181(同樣來自 1970 年)

這些極為久遠的日期導致 Python 的 dateutil 時區計算功能在處理夏令時間轉換和時區轉換時失敗。

修復方法:

兩條 SQL UPDATE 指令用於修正有問題的時間戳記:

sql

-- 修正節目更新時間戳記(設為目前時間)
UPDATE tv_shows SET last_update_indexer = strftime('%s', 'now') WHERE last_update_indexer < 946684800;

-- 修正集數播出日期(設為 NULL/未知)
UPDATE tv_episodes SET airdate = NULL WHERE airdate > 0 AND airdate < 946684800;

解決步驟:

  1. 停止 SickGear 服務(PID 31531)
  2. 備份資料庫(sickbeard.db
  3. 套用 SQL 修正指令以更新有問題的日期
  4. 重新啟動 SickGear,使用 /share/CACHEDEV1_DATA/.qpkg/OSickGear/sickgear.sh start

這個修復方法確保資料庫中的所有日期都在現代時區計算的有效範圍內,讓 SickGear 的網頁介面能再次正常運作,從而解決了溢出錯誤。

哦,不錯!:+1:

那這真的解決了問題嗎?

是的,效果很好。作為一個非程式設計師,能夠讓Claude找出問題、撰寫程式碼並告訴我如何修正,真的非常聰明。

太棒了!

不過,還是值得讓開發人員知道這個問題以及解決方法。這或許有助於防止類似情況再次發生。

嗨,這是什麼錯誤?!

[~] # sherpa check
sherpa v250927-stable
done: actions complete.

• 套件動作開始於 2:15:17 PM,結束於 2:15:24 PM,耗時 7 秒

• 這些套件動作已被略過(原因如下):
    「sign」Entware QPKG 用時 1 秒(已簽署)
    「sign」Par2turbo QPKG 用時 1 秒(已簽署)
    「sign」sherpa QPKG 用時 1 秒(已簽署)
    「sign」OTransmission QPKG 用時 1 秒(已簽署)

• 這個套件動作失敗(原因如下):
    reactivate OTransmission QPKG 用時 2 秒(1)