SSD Nodes Learn 🎉 VPS $5.50/月起
指南 Matt Connor作者: Matt Connor · 已更新 2026-08-13

Claude 系統管理員:6 種日常伺服器工作

Claude 可協助解讀失敗 unit 的日誌、撰寫 systemd unit、檢查 nginx 與 Compose 設定,但私密金鑰、密碼和使用者資料絕不可貼上。

給系統管理員使用的 Claude:先提供建議,再執行操作

Claude 最適合擔任系統管理員的審查工具。貼上日誌摘錄、設定檔、不熟悉的命令或錯誤字串後,Claude 會提供說明,讓你在變更伺服器內容前先行核對。在執行命令前,錯誤答案不會造成任何影響。因此,將模型限制在提供建議的一側,是整體安全機制的核心。

在租用的 Linux VPS(virtual private server)上,每週都會遇到 6 類工作。以下每類工作都提供可行的提示模式、用來驗證答案的命令,以及預期會遇到的失敗模式。這些工作都不需要模型存取你的伺服器。

在 production 伺服器上,執行順序很重要:先閱讀說明,再自行執行檢查,最後決定是否採取行動。在 scratch VM 上可以使用自主操作。但在服務客戶的伺服器上,審查更可靠,因為模型無法看到它所推測的實際狀態。

絕對不可貼上的內容

提示中的所有內容都會離開您的伺服器。以下4類內容必須留在主機上:

  • 私密金鑰:~/.ssh/id_ed25519/etc/ssh/ssh_host_*_key,以及 /etc/letsencrypt/live/ 下的任何 TLS (transport layer security) 金鑰。
  • 憑證檔案:.env~/.aws/credentials/root/.docker/config.json,以及任何檔案或日誌行中的資料庫密碼。
  • 帳戶資料:/etc/shadow/etc/gshadow。沒有任何 sysadmin 問題需要密碼雜湊才能回答。
  • 任何屬於使用者的內容:電子郵件地址、訂單資料列、包含工作階段 cookie 或 PII (personally identifiable information) 的請求日誌。

公開金鑰可以貼上。私密金鑰不行。這兩類檔案乍看之下很相似,因此複製前請先查看第一行:第一行包含 BEGIN OPENSSH PRIVATE KEY 的檔案絕對不可放入提示中。正確區分 SSH 金鑰資料本身就值得花10分鐘了解。

請先遮蔽敏感內容再貼上,不要仰賴自己在200行內容中找出單一權杖:

sudo journalctl -u myapp -n 200 --no-pager | sed -E 's/(token|secret|password|api[_-]?key)[=:][^[:space:]]+/\1=REDACTED/gI'

Docker 有一個特別容易出錯的地方。docker compose config 會將您的 .env 值插入它輸出的內容,因此即使磁碟上的檔案不含秘密,該輸出仍屬於秘密資料。請使用 docker compose config -q;它會驗證設定,但不輸出任何內容。關於代理程式可查看哪些內容的完整政策,請參閱避免讓 AI 代理程式接觸秘密,其中涵蓋環境層面的處理方式。

工作 1:這項服務為何失敗?

先執行能直接提供答案的 2 個命令:

systemctl status myapp.service --no-pager
sudo journalctl -u myapp.service -b -n 100 --no-pager -o short-iso

貼上這 2 個命令的輸出,並補充模型無法自行推測的背景:發行版與版本、最近修改的內容、這項服務是否曾經正常運作,以及故障發生多久。先要求說明機制。

Ubuntu 24.04。myapp.service 在我 1 小時前編輯 unit 之前一直正常。以下是 systemctl status 和最近 100 行 journal。哪一行是第一個真正的錯誤?它代表什麼意思?先不要提供修正方法。

提示中的「先不要提供修正方法」很重要。日誌通常會被後續重試產生的訊息掩蓋,因此要求模型提供修正方法時,模型可能只會解釋最後看到的那一行。真正重要的行通常位於這些雜訊上方約 20 行處。

最終通常會得到類似 Main PID: 1841 (code=exited, status=203/EXEC) 的行。結束狀態 203/EXEC 表示 kernel 無法執行 ExecStart 中指定的檔案:路徑不存在,或檔案存在但沒有執行權限。#! 中指定的 interpreter 若未安裝,也會產生相同的狀態。上述情況都可使用 ls -lhead -1 進行驗證。

失敗模式:模型捏造原因。貼上的內容太少時,模型會用通用原因填補空白,例如「連接埠已被使用」。此時應反問:「我提供的內容中,哪一行支持這個說法?」如果無法在文字中指出依據,這個原因就是猜測。

工作 2:撰寫 systemd unit 或 cron 項目

提供 unit file 所需的資訊:確切的命令、執行身分、工作目錄、是否必須等待網路就緒,以及以非零狀態結束時應採取的處理方式。啟用任何項目之前,先確認回傳結果。

sudo systemd-analyze verify /etc/systemd/system/myapp.service
sudo systemctl daemon-reload
sudo systemctl start myapp.service
systemctl status myapp.service --no-pager

systemd-analyze verify會依照 systemd 的方式剖析檔案,因此能抓出人工檢視時容易忽略的問題。拼錯 directive 時會輸出 /etc/systemd/system/myapp.service:7: Unknown key name 'Enviroment' in section 'Service', ignoring.。缺少 binary 時會輸出 Command /usr/local/bin/myapp is not executable: No such file or directory。這兩種錯誤在 daemon-reload期間都不會顯示,因此 unit 可能順利載入,實際執行時卻立即失敗。

撰寫時有兩個錯誤一再出現。第一個是 After=network.target。它只表示網路堆疊已設定完成,不代表位址已經存在。服務若繫結至特定 IP,開機時會因 bind: Cannot assign requested address而失敗;修正方式是搭配 After=network-online.target使用 Wants=network-online.target。第二個是對會 daemonise 的程式使用 Type=simple:systemd 會將第一個程序視為服務,父程序隨即結束,unit 會被標記為已停止,但實際程序仍在未受管理的情況下執行。

若要設定排程,請實際檢查,而不要只閱讀內容:

systemd-analyze calendar 'Mon *-*-* 04:00:00'

這會輸出正規化後的內容,以及該運算式下一次觸發的時間,從而確認其實際意義。若你正在 timer 與 crontab 之間做選擇,VPS 上的 systemd services 與 timers說明了兩者的取捨。

Cron 有一個陷阱,除非你特別詢問,否則沒有模型會主動提醒你。Cron 會以精簡的環境執行工作,因此 PATH大致等於 /usr/bin:/bin,而且永遠不會讀取 shell profile。直接貼到終端機中可以正常執行的工作,在 cron 下卻會因 /bin/sh: 1: docker: not found而失敗,因為該 binary 位於 /usr/local/bin。請在 crontab 中使用絕對路徑。

工作 3:上線前檢查 nginx 或 Compose 檔案

這項工作的效益最高。貼上檔案,說明它應該執行的功能,並要求逐行說明它實際執行的內容。

這個 vhost 應透過 HTTPS 提供 example.com,並將 /api 代理到本機 8080 埠上的服務。請重新逐字說明內容,並指出任何不符合上述描述的部分。

接著執行了解語法的工具:

sudo nginx -t
docker compose config -q

nginx -t 會輸出 nginx: configuration file /etc/nginx/nginx.conf test is successful,或列出檔案名稱與行號,例如 nginx: [emerg] unknown directive "proxy_pas" in /etc/nginx/conf.d/app.conf:12。檔案通過剖析時,docker compose config -q 不會輸出任何內容;縮排錯誤時,則會輸出類似 yaml: line 7: did not find expected key 的直接錯誤訊息。

這兩個工具都不會檢查設定意圖。通過 nginx -t 的設定,仍可能代理到錯誤的連接埠,或在你原本要使用 127.0.0.1 時監聽 0.0.0.0。這就是模型能發揮作用的地方,也是它會出錯的地方:要求它修正一個 directive 時,它經常會重寫並回傳整份檔案,還悄悄遺漏你原有的兩個 directive。請要求它列出變更的行,以及每項變更的原因,然後手動編輯。

確認實際公開的內容:

sudo ss -tulpn

沒有 sudo 時,你只能看到監聽中的 socket,看不到擁有這些 socket 的處理程序。如果輸出結果令人意外,請參閱連接埠的用途及 Linux 如何繫結連接埠,內容較短。

工作 4:執行不熟悉的命令前,先說明它的作用

貼上命令,並針對它提出 4 個問題:每個 flag 的作用是什麼、它會寫入什麼、它會刪除什麼,以及重複執行時會發生什麼。最後一個問題能避免的損害,往往比其他問題更多。

find /var/log -name '*.gz' -mtime +7 -delete 為例。良好的說明會指出,-mtime +7 會計算完整的 24 小時週期並捨棄零數,因此它會比 7 天更嚴格,符合至少 8 天前的檔案,而不是 7 天前的檔案。說明也應指出,find 會由左至右評估運算式,因此若將 -delete 移到 -name 前面,就會刪除起始路徑下的所有內容。find 的 man page 將第二點列為警告,而這個錯誤曾讓人失去 /var/log

再以 rsync -a --delete /srv/app/ /backup/app/ 為例。來源路徑末尾的斜線表示「此目錄的內容」。移除斜線後,結果會是 /backup/app/app/。加入 --delete 後,目的地中來源沒有的內容也會被刪除;對鏡像而言這是正確行為,但若來源路徑錯誤,就會造成災難。

使用工具驗證,不要依賴模型:

rsync -a --delete --dry-run /srv/app/ /backup/app/ | head -20
find /var/log -name '*.gz' -mtime +7

執行 find 時不加上 -delete,會取得清單,而不是造成資料遺失。

失敗模式:捏造 flag。對於具有 30 年文件記錄的工具,模型通常很可靠;但對 vendor CLI(command line interfaces)和近期的子命令,可靠度低得多。模型可能產生看似合理、實際不存在的 flag。--help 可在 1 秒內確認結果。引號是另一個常見弱點。因此,當命令包裝 $(...) 運算式時,請閱讀 命令替換在命令執行前如何展開,不要只相信說明。

工作 5:將 shell 歷史記錄整理成操作手冊

你剛花了 2 個小時讓某項工作正常運作。相關知識只存在於終端機回捲內容中,下個月就會消失。

history 200 > /tmp/session.txt

讀取該檔案,並在檔案離開主機前,刪除每一行包含密碼、token 或客戶識別碼的內容。在 Linux 主機上,shell 歷史記錄是最可靠的 secret 尋找來源之一,因為每個人至少都曾將 secret 直接輸入命令列一次。在 ~/.bashrc 中設定 HISTCONTROL=ignorespace 後,以空格開頭的命令完全不會寫入歷史記錄。

要產生可用操作手冊,提示內容應要求驗證,不只是列出步驟:

這是一段將全新的 Debian 13 主機設定為可正常運作 Postgres 安裝的 shell 工作階段。請將其整理成編號操作手冊。每個步驟只使用一個命令。每個步驟後提供可證明操作成功的命令,並說明正常輸出應呈現的內容。標示任何依賴我的特定主機的步驟。

失敗模式:整理成過度簡潔的故事。你的工作階段中有一個步驟曾經錯誤 2 次,之後才修正;模型會抹平這段過程,因為刪除它後,逐字記錄看起來更整齊。請將操作手冊與歷史記錄比對,補回修正內容。模型也會編造看似合理的驗證命令,因此請在儲存檔案前,逐一執行它產生的所有檢查。如果操作手冊涵蓋首次開機,請對照 新 VPS 的前 10 分鐘,避免記錄下比既有解法更差的版本。

工作 6:將錯誤訊息轉換為修正方式

貼上完整的字串、產生該字串的命令,以及錯誤出現前唯一變更的項目。要求列出依可能性排序的原因,並為每個原因提供可區分的命令,迫使答案具備可測試性。

nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)。請依可能性排序列出原因,並為每個原因提供一個可確認或排除該原因的命令。

對於該錯誤,發生機制沒有歧義:另一個程序已占用 port 80,而 sudo ss -tulpn | grep ':80 ' 會指出該程序。常見情況包括失敗的 reload 留下第二個 nginx master,或 Apache 被當作相依服務載入,並由其自身的套件啟動。

失敗模式:修正方式只是掩蓋原因。chmod 777--privileged、停用 SELinux,以及以 root 身分執行服務,都會讓錯誤消失。在模型說明狹義權限為何不足之前,拒絕任何會擴大權限的修正方式。該說明才是真正的答案。替代方案只能讓錯誤停止顯示。

它可靠地處理錯誤的地方

  • 它看不到你的伺服器。每個回答都只取決於你貼出的內容,而且不會告訴你摘錄過短。
  • 它會混淆版本。套件名稱與預設旗標會因發行版和版本而變動,而模型會將所有版本的資訊平均混用。
  • 即使錯了,它仍能流暢作答。虛構的運作機制讀起來和正確機制完全相同,因此上述每個原因都會搭配一個可用來驗證的命令。
  • 長時間的工作階段中,它會失去脈絡。兩小時對話開頭的資訊,到了結尾便不再影響回答。

最後一點比較像是工作方式的問題,而不是模型本身的問題。實際的解法是管理長時間 Claude Code 工作階段中的脈絡:縮短工作階段,每次只處理一項工作。

在伺服器本機執行 agent

以上內容都只需複製貼上,因此模型不會接觸你的機器。當它在伺服器上執行、讀取檔案並執行命令後,風險型態就會改變:錯誤的命令可能導致服務中斷。請為它建立專用的非特權使用者,不要使用 root。熟悉其行為前,請避免在正式環境的伺服器上執行。執行前也應先建立 snapshot。在 VPS 上安全執行 Claude Code說明 sandboxing 與權限模型。在 tmux 中執行 Claude Code則處理另一項問題,因為 SSH (secure shell) 連線中斷時,前景執行中的 agent 會在工作完成前停止。請依照建立服務帳號的方式建立此帳號;VPS 上的最小權限使用者提供了詳細說明。

FAQ

Claude 能直接讀取我的伺服器日誌嗎?

不能直接讀取。聊天介面只能看到您貼上的文字。在伺服器上以命令列工具執行的 Claude Code,能依啟動它的使用者權限讀取檔案及執行命令,因此涉及更高程度的信任。對一般支援問題而言,貼上經過遮罩處理的 100 行摘錄,比授予 agent shell 存取權更快速也更安全。

我絕對不應從伺服器貼上哪些內容?

私密金鑰、.env 檔案及其他認證資料儲存區、/etc/shadow,以及任何屬於使用者的資料。日誌摘錄送入提示之前,請先遮罩 token。有一種不太明顯的情況:docker compose config 的輸出會將您的 .env 值插入其中,因此請使用 docker compose config -q;它會驗證檔案,但不輸出任何內容。

讓 Claude 在正式環境 VPS 上執行命令安全嗎?

請將它視為一名不了解環境的新管理員:讀取可以,寫入則需要審查。在正式環境中,請要求它說明原因,然後由您自行執行命令。如果確實要讓 agent 執行命令,請提供沒有廣泛 sudo 權限的專用非特權帳號,並先在 staging 主機上開始;這樣即使出錯,代價也是重新建置,而不是造成服務中斷。

為什麼 Claude 會建議不存在的 flag?

因為它會預測看似合理的文字,而合理的 flag 看起來與真正的 flag 相同。這種情況最常發生在廠商 CLI 與較新的子命令上,因為模型取得的文件不完整,或文件自此已經變更。--helpman 才是判定依據;任何會刪除或覆寫資料的命令,都應先進行 dry run。

啟用 systemd unit 前,如何檢查它?

執行 sudo systemd-analyze verify /etc/systemd/system/myapp.service。它會使用 systemd 自身的 parser 解析檔案,回報未知 directive 及其行號,並標示遺失或不可執行的 ExecStart binary。接著執行 daemon-reloadstart,並閱讀 systemctl status,再執行 enable;因為能順利載入的 unit,第一次執行時仍可能失敗。