Skip to main content

diagnose-job

Use when a user asks why a Spur (or Slurm-compatible) job failed, is stuck, won't start, crashed, timed out, got OOM-killed, or is otherwise misbehaving. Covers ALL job states: PENDING, RUNNING (hung/slow), COMPLETING (stuck), FAILED, CANCELLED, TIMEOUT, NODE_FAIL, OUT_OF_MEMORY, PREEMPTED, SUSPENDED, DEADLINE, and submit-time rejections. Triggered by phrases like "why isn't my job running", "job stuck", "job failed", "OOM killed", "job timed out", "job cancelled", "squeue shows PD/F/CA/TO", "exit code non-zero", "diagnose job", "debug scheduling". Accepts a job ID or inspects all problem jobs when none is given. Requires SSH or local access to a host with the `spur`/`scontrol`/`squeue` CLI and connectivity to the controller (port 6817).

الانتقال إلى التثبيت

معلومات المصدر

المستودع
ROCm/spur-toolkit
آخر نشاط في المصدر
١٤ سبتمبر ٢٠٢٦ في ٢١:٤٢
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٢
التفرعات
٤

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
diagnose-job
description
Use when a user asks why a Spur (or Slurm-compatible) job failed, is stuck, won't start, crashed, timed out, got OOM-killed, or is otherwise misbehaving. Covers ALL job states: PENDING, RUNNING (hung/slow), COMPLETING (stuck), FAILED, CANCELLED, TIMEOUT, NODE_FAIL, OUT_OF_MEMORY, PREEMPTED, SUSPENDED, DEADLINE, and submit-time rejections. Triggered by phrases like "why isn't my job running", "job stuck", "job failed", "OOM killed", "job timed out", "job cancelled", "squeue shows PD/F/CA/TO", "exit code non-zero", "diagnose job", "debug scheduling". Accepts a job ID or inspects all problem jobs when none is given. Requires SSH or local access to a host with the `spur`/`scontrol`/`squeue` CLI and connectivity to the controller (port 6817).
# diagnose-job — Full job lifecycle diagnostician You are a Spur cluster job diagnostician. Your task is to determine exactly why a job is not behaving as expected — whether it won't start, is running but stuck, failed, got killed, or disappeared — and give the user a concrete, actionable fix. Spur is a Slurm-compatible job scheduler. Its CLI (`spur`, `squeue`, `scontrol`, `sinfo`, `sdiag`, `sacctmgr`, `sprio`, `sacct`, `sstat`) works identically to Slurm's. All commands below work on both Spur and Slurm clusters. ## Job state reference | State | Code | Meaning | |-------|------|---------| | PENDING | PD | Waiting to be scheduled | | RUNNING | R | Executing on node(s) | | COMPLETING | CG | Process done, epilog/cleanup in progress | | COMPLETED | CD | Finished successfully (exit 0) | | FAILED | F | Exited non-zero | | CANCELLED | CA | Killed by user/admin/dependency | | TIMEOUT | TO | Hit wall-time limit | | NODE_FAIL | NF | Node died mid-execution | | OUT_OF_MEMORY | OOM | Killed by cgroup OOM | | PREEMPTED | PR | Evicted by higher-priority job | | SUSPENDED | S | Paused (admin or preempt-suspend) | | DEADLINE | DL | Missed --deadline window | | REQUEUED | RQ | Transient — returns to PENDING | ## Node state reference | State | Display | Schedulable? | Meaning | |-------|---------|-------------|---------| | Idle | idle | Yes | No jobs running | | Allocated | alloc | No | All CPUs in use | | Mixed | mix | Yes (partial) | Some CPUs free | | Down | down | No | Heartbeat lost or admin-set | | Drain | drain | No | Admin hold, no new jobs | | Draining | drng | No | Finishing current jobs, then drain | | Error | err | No | Agent error / crash loop | | Unknown | unk | No | Not yet registered | | Suspended | susp | No | Power-managed / suspended | **Overlays** (displayed as **replacements** in `sinfo` — the base state is hidden): - `plnd` — backfill scheduler reserved a future slot on this node (base: idle) - `resv` — held by an admin reservation - `maint` — reserved for maintenance --- ## Step 0 — Gather context Ask the user only what you cannot infer: | Need | How to get it | |------|---------------| | **Job ID** | Ask if not provided. If "all my jobs" or "everything is broken", scan broadly. | | **Symptom** | "Won't start", "failed", "OOM", "timed out", "disappeared", "stuck completing", "cancelled but I didn't cancel it", etc. This determines which diagnostic path to follow. | | **Access method** | Local CLI or SSH? If SSH, get hostname + jump host. | | **Controller endpoint** | Default `http://localhost:6817`. Only ask if non-standard. | ```bash JOB_ID=<id> # leave empty for broad scan ``` --- ## Step 1 — Snapshot cluster and job state Run these in parallel: ```bash # 1a. Full job details if [ -n "${JOB_ID}" ]; then scontrol show job "${JOB_ID}" else squeue --format="%18i %12j %10u %8T %12r %10M %10l %6D %R" fi # 1b. Node overview (all states including alloc, mix, idle overlays) sinfo -N --format="%20N %10P %6t %10e %10m %20G %30f" # Reason field is not available via sinfo format; use scontrol for drain/down reasons: scontrol show node | grep -E "NodeName|State|Reason" # 1c. Partition state scontrol show partition # 1d. Scheduler health sdiag ``` For a specific job, also run: ```bash # 1e. Accounting record (works for finished jobs too) # Note: sacct supported fields are JobID,JobName,User,Account,Partition,State, # ExitCode,DerivedExitCode,Elapsed,NNodes,NCPUS,QOS,TimeLimit,NodeList, # Start,End,Submit,PreemptedBy,PreemptMode,PreemptQOS # Note: ReqMem is accepted as a field name but always displays "?" (not yet wired) sacct -j "${JOB_ID}" --format=JobID,JobName,State,ExitCode,Elapsed,NodeList,Start,End # 1f. Live resource usage for RUNNING jobs (MaxRSS, MaxVMSize are sstat fields, not sacct) sstat -j "${JOB_ID}" 2>/dev/null # 1g. Priority breakdown (pending only) sprio -j "${JOB_ID}" 2>/dev/null # 1h. Projected start time (pending only) squeue --start -j "${JOB_ID}" 2>/dev/null ``` > **If `scontrol show job` returns "Invalid job id"**: the job already completed and > was purged from controller memory (`terminal_job_retention_secs`, default 3600). > Use `sacct -j <id>` instead — it queries the accounting database. Now branch on the job's **state**. --- ## PENDING jobs (State=PD) Extract the `Reason=` field from `scontrol show job`. This is the primary diagnostic signal. Match it to one of these categories: ### A. Resource shortage — `Resources` All suitable nodes are busy. The job is next in line but no capacity exists. ```bash squeue --states=R --sort=-T --format="%18i %12j %10u %10M %10l %6D %R" | head -30 # Note: plnd is an overlay on idle nodes (displayed as a replacement, not suffix) sinfo -N --format="%20N %10P %6t %20G %30f" ``` **Diagnosis:** Show busy (alloc/mix) vs idle vs backfill-reserved (`plnd`) nodes. Report projected start from `squeue --start`. Check if the job requests more resources than any single node has (unsatisfiable). **Fixes:** 1. Wait — report projected start time. 2. Tighter `--time` estimates let backfill pack more efficiently. 3. If requesting more GPUs/CPUs than any node has, reduce or use `--nodes` for multi-node. 4. Preemptible QOS if the user can tolerate eviction. ### B. Priority starvation — `Priority` Higher-priority jobs keep being scheduled first. ```bash sprio -j "${JOB_ID}" sprio --sort=-Y | head -20 sshare --user="${USER}" 2>/dev/null ``` **Fixes:** 1. Wait — priority increases with age. 2. Admin raises priority: `scontrol update JobId=${JOB_ID} Priority=<N>` 3. Move to higher `priority_tier` partition. 4. Enable preemption. ### C. Dependency — `Dependency` / `DependencyNeverSatisfied` ```bash scontrol show job "${JOB_ID}" | grep -E "Dependency|JobId" scontrol show job <dep_id> | grep -E "JobId|JobState|ExitCode" ``` - `DependencyNeverSatisfied`: target failed/cancelled/timed out. Fix: `scontrol release ${JOB_ID}` or resubmit. - Circular dependency: cancel one leg. - `afterok` on a job that exited non-zero: will never satisfy. ### D. Hold — `JobHeldUser` / `JobHeldAdmin` / `JobHoldMaxRequeue` Internal enum names: `Held` (displays as `JobHeldUser`), `JobHeldAdmin`, `JobHoldMaxRequeue`. ```bash scontrol release "${JOB_ID}" ``` `JobHoldMaxRequeue`: job hit `max_batch_requeue` (default 5). Check controller logs for the root cause (prolog failure? node crash?) before releasing. ### E. Partition problems — `PartitionInactive` / `PartitionNodeLimit` / `PartitionTimeLimit` / `PartitionConfig` ```bash scontrol show partition <partition_name> ``` - `PartitionInactive`: partition is down/inactive — admin brings it up or user moves partitions. - `PartitionNodeLimit`: job needs more nodes than the partition physically has. - `PartitionTimeLimit`: `--time` exceeds partition `MaxTime`. - `PartitionConfig`: `--nodes` exceeds partition `MaxNodes` or below `MinNodes`, or other config violation. ### F. Node problems — `NodeDown` / `ReqNodeNotAvail` / `BadConstraints` ```bash scontrol show job "${JOB_ID}" | grep -E "ReqNodeList|ExcNodeList|Features|ReqTRES" sinfo -N --format="%20N %10P %6t %10c %10m %20G %30f" scontrol show node | grep -E "NodeName|State|Reason" ``` - `BadConstraints`: `--constraint` features match zero nodes. Show the mismatch. - `ReqNodeNotAvail`: named nodes down/draining/wrong partition. - Fix: remove constraints, or admin recovers nodes. ### G. QOS / Association limits Each QOS/Association limit has its own pending reason with a specific display string. **QOS limit reasons** (note: GPU limits display as `GRES`, not `GPU`): | Reason display | Meaning | |---------------|---------| | `QOSMaxJobsPerUserLimit` | Running jobs per user exceeded | | `QOSMaxCpuPerJobLimit` | CPUs per job exceeded | | `QOSMaxNodePerJobLimit` | Nodes per job exceeded | | `QOSMaxMemoryPerJob` | Memory per job exceeded | | `QOSMaxGRESPerJob` | GPUs per job exceeded | | `QOSMaxWallDurationPerJobLimit` | Wall-time per job exceeded | | `QOSMaxCpuPerUserLimit` | Total CPUs across user's jobs exceeded | | `QOSMaxNodePerUserLimit` | Total nodes across user's jobs exceeded | | `QOSMaxMemoryPerUser` | Total memory across user's jobs exceeded | | `QOSMaxGRESPerUser` | Total GPUs across user's jobs exceeded | | `QOSMaxSubmitJobPerUserLimit` | Submit count per user exceeded | | `MaxSubmitJobsPerAccount` | Submit count per account exceeded | | `QOSGrpCpuLimit` | Group-wide CPU aggregate exceeded | | `QOSGrpNodeLimit` | Group-wide node aggregate exceeded | | `QOSGrpMemLimit` | Group-wide memory aggregate exceeded | | `QOSGrpGRES` | Group-wide GPU aggregate exceeded | | `QOSGrpWallLimit` | Group-wide wall-time aggregate exceeded | | `QOSGrpSubmitJobsLimit` | Group-wide submit count exceeded | **Association limit reasons:** | Reason display | Meaning | |---------------|---------| | `AssocMaxJobsLimit` | Running jobs for this association exceeded | | `AssocMaxSubmitJobLimit` | Submit count exceeded | | `AssocMaxCpuPerJobLimit` | CPUs per job exceeded | | `AssocMaxNodePerJobLimit` | Nodes per job exceeded | | `AssocMaxMemPerJob` | Memory per job exceeded | | `AssocMaxGRESPerJob` | GPUs per job exceeded | | `AssocMaxWallDurationPerJobLimit` | Wall-time per job exceeded | | `AssocGrpCpuLimit` | Group CPU aggregate exceeded | | `AssocGrpNodeLimit` | Group node aggregate exceeded | | `AssocGrpMemLimit` | Group memory aggregate exceeded | | `AssocGrpGRES` | Group GPU aggregate exceeded | | `AssocGrpSubmitJobsLimit` | Group submit count exceeded | **Checks:** ```bash sacctmgr show user "${USER}" withassoc format=User,Account,MaxJobs,MaxSubmit,MaxTRES,GrpTRES sacctmgr show qos format=Name,MaxJobsPU,MaxSubmitPU,MaxTRES,MaxTRESPU,GrpTRES,GrpJobs squeue --user="${USER}" --states=R | wc -l ``` Identify which limit is hit, show current usage vs configured cap. Fix: wait, reduce request, or admin raises limit. ### H. Deferred start — `BeginTime` ```bash scontrol show job "${JOB_ID}" | grep -E "EligibleTime|StartTime" ``` Fix: cancel and resubmit without `--begin`, or admin adjusts the job's start constraints. ### I. Reservation — `Reservation` / `ReqNodeNotAvail, Reserved for maintenance` / `ReservationDeleted` ```bash scontrol show reservation ``` - `Reservation`: nodes held by a reservation the job can't access. - `ReservationDeleted`: the reservation was deleted while the job was held for it. - Fix: wait for window, admin adds user to reservation, or submit with `--reservation`. ### J. Job array throttle — `JobArrayTaskLimit` Array `%N` concurrency cap reached. Fix: wait for current tasks to complete, or cancel and resubmit with a higher `--array` throttle (e.g. `--array=0-99%20`). ### K. License shortage — `Licenses` ```bash scontrol show license ``` Fix: wait or reduce `--licenses` request. ### L. Launch failure — `JobLaunchFailure` ```bash scontrol show job "${JOB_ID}" | grep -E "Reason|AdminComment" ``` Prolog failed, container pull failed, or agent rejected. Check controller logs, fix root cause, then `scontrol release ${JOB_ID}`. ### M. Kubernetes reserved — `ReqNodeNotAvail, Reserved for Kubernetes cluster` Nodes in managed k0s cluster are excluded. The pending reason displays as `ReqNodeNotAvail, Reserved for Kubernetes cluster`. Use non-k0s nodes. ### N. Accounting / validation — `AccountingUnavailable` / `InvalidQOS` - `AccountingUnavailable`: QOS or association limit caches not yet readable (e.g. after controller restart while association data loads). Check `systemctl status spurctld`. - `InvalidQOS`: QOS doesn't exist in the QOS cache. Check `sacctmgr show qos`. > Note: `InvalidAccount` exists as a declared reason but is never assigned as a pending > reason in current code. Account issues surface as submit-time rejections instead. ### O. Scheduler depth limit `Reason=Priority` or `Resources` but `LastSchedEval` is stale. ```bash sdiag | grep -E "depth|max_jobs" ``` Fix: admin increases `scheduler.max_jobs_per_cycle` and runs `scontrol reconfigure`. ### P. Requeue-related pending reasons When a job is requeued (after failure, timeout, OOM, signal, preemption, or node boot failure), the pending reason reflects WHY it was requeued: | Reason display | Meaning | |---------------|---------| | `TimeLimit` | Previous run exceeded wall-time (requeued after timeout) | | `NonZeroExitCode` | Previous run exited non-zero (requeued after failure) | | `RaisedSignal` | Previous run was killed by a signal | | `OutOfMemory` | Previous run was OOM-killed (requeued) | | `BootFailure` | Node boot failure prevented start (requeued) | | `Preempted` | Job was preempted, now re-pending in requeue mode | These differ from the terminal states (TIMEOUT, FAILED, OOM, etc.) — they appear on jobs that are back in PENDING after a requeue. Check the job's `Restarts` count and controller logs for the original failure.
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub