この記事で切り分けられること
PowerShellを呼び出す監視スクリプトでエラーコードが大量に出た時、それが本当のコードの不具合なのか、PowerShellや関連プロセスの終了コードの意味を取り違えて「失敗」として数えてしまっているだけなのかを切り分ける方法を、実際に1件ずつ実測して直した記録として書く。
症状
本人から「いろいろとエラーが出まくっているんだけど」という報告があった。点検スクリプト(run_health_check.py)の要対応は4件。内訳を1件ずつ実測したところ、本当のコードの不具合は1件だけだった。
| 出ていた物 | 実際 |
|---|---|
vps_watchdog が毎回エラー | 本物の不具合。fetch_tasks() の PowerShell 呼び出しが120秒を超えて TimeoutExpired で落ちていた(11/05 20:00:27)。直前19:11にPCが休止から復帰し、20:00は定時タスクが重なる時刻。Get-ScheduledTask | Get-ScheduledTaskInfo は1本ずつ問い合わせるため、負荷が高いと2分を超えることがある |
タスクの rc=0x800710E0 | PCが休止中でWindowsが起動を断った印。コード側の不具合ではない |
| 「ジョブ失敗」 | 回線が切れた時の ConnectionAbortedError / WinError 10053。NET_DOWN の語彙に無く、恒久の失敗として数えていた |
rc=0x41301(=267009) | 「いま走っている」という意味のコード。失敗として数えていた |
原因
見張り役(watchdog)が、タスク情報の取得に失敗したら例外で落ちる作りだった。さらに点検スクリプト側が、回復する失敗(電源の都合・回線切断・実行中)を、恒久の失敗と同じ欄に積んでいた。結果として画面は赤いのに直す物が無く、本物の1件が同じ山に埋もれていた。
直し方
見張り役は、取得に失敗しても落とさずに空を返して次の回に回すようにする。
# run_task_watchdog.py 側のイメージ
def fetch_tasks():
try:
result = subprocess.run(
["powershell", "-Command",
"Get-ScheduledTask | Get-ScheduledTaskInfo"],
capture_output=True, text=True, timeout=300 # 120 -> 300
)
if result.returncode != 0:
return [] # 空で返して続行。落とさない
return json.loads(result.stdout)
except subprocess.TimeoutExpired:
return []
except json.JSONDecodeError:
return []
点検スクリプト側は、回復する失敗を赤(bad)ではなく情報(info)の欄に分ける。
# run_health_check.py 側のイメージ
NET_DOWN = (
"ConnectionAbortedError",
"WinError 10053",
"Connection aborted",
"RemoteDisconnected",
"ProtocolError",
"IncompleteRead",
)
# fails から実行中(267009)は除外する
if rc == 267009:
continue
# 電源起因・回線起因は bad ではなく info へ
if rc == 0x800710E0 or any(s in message for s in NET_DOWN):
info.append(item)
else:
bad.append(item)
この修正で、要対応は4件から1件に減った。残る1件が、実際に対応が要る本物の不具合だった。
それでも駄目なときに次に見る場所
- 見張り役(watchdogの類)が、取得に一度失敗しただけで自分ごと止まっていないか確認する。止まる作りだと、監視対象ではなく監視自体が障害になる。
- 点検スクリプトの「赤」が増えた時は、1件ずつ実測して、電源・回線・実行中のような回復する状態を恒久の失敗と同じ欄に積んでいないか確認する。赤の数を増やすと、本物の1件が埋もれる。
- rc の数値をそのまま「失敗」として扱う前に、意味を1つずつ引く。たとえば次のような対応関係がある。
数字だけを見て分類を足すと、同じ取り違えを別の箇所でも起こす。0x41301 (267009) = 実行中 0x41303 = 未実行 0x800710E0 = 電源の都合で起動を断った - タイムアウトの値を伸ばしても再発する場合は、PCの休止復帰の直後や定時タスクが重なる時間帯に処理が集中していないか、実行時刻を記録して確認する。

Claude Codeとは何か、実際に投げた依頼文と直し方から説明する
Notion API連携の最初の設定をインテグレーション作成から実際に動かす手順
CSVの文字化けと列ずれが止まる場所をPythonのコードで具体的に潰す手順