Skip to content

Commit 6ed92aa

Browse files
Suppress slurm log files and add session guardrails
Send sbatch stdout/stderr to /dev/null so slurm-*.out files don't litter the working directory. Also block nested sinteractive launches, enforce interactive job limits before submitting, and show other running sessions on disconnect. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent faafa8b commit 6ed92aa

1 file changed

Lines changed: 144 additions & 1 deletion

File tree

scripts/sinteractive

Lines changed: 144 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@ function main {
108108
return
109109
fi
110110

111+
# Don't allow launching sinteractive from inside an existing session
112+
if [[ -n "$TMUX" ]] && [[ "$TMUX" == *sinteractive* ]]; then
113+
echo 1>&2 "Error: Already inside an sinteractive session. Exit this session first."
114+
exit 1
115+
fi
116+
111117
# Parse custom flags before passing remaining args to sbatch
112118
local args=()
113119
local reattach_jobid=''
@@ -193,9 +199,17 @@ function main {
193199
set -- --signal=B:USR1@600 "$@"
194200
fi
195201

202+
# Check interactive job limit before submitting
203+
local partition
204+
partition=$(get_partition_from_args "$@")
205+
206+
if ! check_job_limit "$partition"; then
207+
exit 1
208+
fi
209+
196210
local output
197211
local sbatch_ec
198-
output=$(sbatch "$@" "${BASH_SOURCE[0]}" tmux)
212+
output=$(sbatch --output=/dev/null --error=/dev/null "$@" "${BASH_SOURCE[0]}" tmux)
199213
sbatch_ec=$?
200214

201215
JOB_ID=$(<<<"${output}" egrep -o -e '\b[0-9]+$')
@@ -255,8 +269,43 @@ function main {
255269
echo 1>&2 ''
256270
echo 1>&2 "To cancel the job:"
257271
echo 1>&2 " scancel ${JOB_ID}"
272+
273+
# Show other running sinteractive sessions
274+
local other_running
275+
other_running=$(squeue --me --states RUNNING --noheader \
276+
--Format=JobID:12,Comment:30,NodeList:16,TimeUsed:12,TimeLimit:12 2>/dev/null \
277+
| grep sinteractive | grep -v "^${JOB_ID} ")
278+
279+
if [[ -n "$other_running" ]]; then
280+
echo 1>&2 ''
281+
echo 1>&2 'Other running sinteractive sessions:'
282+
printf 1>&2 ' %-10s %-14s %-10s %-10s\n' 'JOBID' 'NODE' 'ELAPSED' 'TIMELIMIT'
283+
while read -r jobid comment node elapsed limit; do
284+
printf 1>&2 ' %-10s %-14s %-10s %-10s\n' "$jobid" "$node" "$elapsed" "$limit"
285+
done <<< "$other_running"
286+
fi
258287
else
259288
echo 1>&2 "Session ended. Job ${JOB_ID} is no longer running."
289+
290+
# Show any remaining sinteractive sessions
291+
local remaining
292+
remaining=$(squeue --me --states RUNNING --noheader \
293+
--Format=JobID:12,Comment:30,NodeList:16,TimeUsed:12,TimeLimit:12 2>/dev/null \
294+
| grep sinteractive)
295+
296+
if [[ -n "$remaining" ]]; then
297+
echo 1>&2 ''
298+
echo 1>&2 'You have other sinteractive sessions still running:'
299+
printf 1>&2 ' %-10s %-14s %-10s %-10s\n' 'JOBID' 'NODE' 'ELAPSED' 'TIMELIMIT'
300+
while read -r jobid comment node elapsed limit; do
301+
printf 1>&2 ' %-10s %-14s %-10s %-10s\n' "$jobid" "$node" "$elapsed" "$limit"
302+
done <<< "$remaining"
303+
echo 1>&2 ''
304+
echo 1>&2 'To free slots, cancel sessions you no longer need:'
305+
while read -r jobid _rest; do
306+
echo 1>&2 " scancel $jobid"
307+
done <<< "$remaining"
308+
fi
260309
fi
261310
}
262311

@@ -281,6 +330,100 @@ function list_sessions {
281330
exit 0
282331
}
283332

333+
# Extract the effective partition name from the processed argument list.
334+
function get_partition_from_args {
335+
while [[ $# -gt 0 ]]; do
336+
case "$1" in
337+
--partition=*)
338+
echo "${1#--partition=}"
339+
return
340+
;;
341+
-p)
342+
echo "$2"
343+
return
344+
;;
345+
*)
346+
shift
347+
;;
348+
esac
349+
done
350+
echo "interactive"
351+
}
352+
353+
# Check if submitting another job would exceed the QOS MaxJobsPerUser limit.
354+
# Only checks when targeting the interactive partition.
355+
# Falls through silently if sacctmgr or squeue are unavailable.
356+
function check_job_limit {
357+
local partition="$1"
358+
359+
# Only enforce for the interactive partition
360+
if [[ "$partition" != "interactive" ]]; then
361+
return 0
362+
fi
363+
364+
# Query QOS limit dynamically; fail open if sacctmgr unavailable
365+
local max_jobs
366+
max_jobs=$(sacctmgr show qos interactive format=MaxJobsPerUser --noheader --parsable2 2>/dev/null)
367+
if [[ $? -ne 0 ]] || [[ -z "$max_jobs" ]]; then
368+
return 0
369+
fi
370+
371+
max_jobs=$(echo "$max_jobs" | xargs)
372+
373+
if ! [[ "$max_jobs" =~ ^[0-9]+$ ]]; then
374+
return 0
375+
fi
376+
377+
# Count current running + pending jobs on the interactive partition
378+
local current_jobs
379+
current_jobs=$(squeue --me --partition=interactive --states=RUNNING,PENDING --noheader 2>/dev/null | wc -l)
380+
if [[ $? -ne 0 ]]; then
381+
return 0
382+
fi
383+
384+
current_jobs=$(echo "$current_jobs" | xargs)
385+
386+
if (( current_jobs >= max_jobs )); then
387+
echo 1>&2 ""
388+
echo 1>&2 "Error: You already have ${current_jobs}/${max_jobs} interactive jobs (the maximum allowed)."
389+
echo 1>&2 ""
390+
391+
local lines
392+
lines=$(squeue --me --partition=interactive --states=RUNNING,PENDING --noheader \
393+
--Format=JobID:12,Name:20,NodeList:16,State:10,TimeUsed:12,TimeLimit:12 2>/dev/null)
394+
395+
if [[ -n "$lines" ]]; then
396+
echo 1>&2 "Your current interactive jobs:"
397+
echo 1>&2 ""
398+
printf 1>&2 ' %-10s %-18s %-14s %-9s %-10s %-10s\n' \
399+
'JOBID' 'NAME' 'NODE' 'STATE' 'ELAPSED' 'TIMELIMIT'
400+
while IFS= read -r line; do
401+
read -r jobid name node state elapsed limit <<< "$line"
402+
printf 1>&2 ' %-10s %-18s %-14s %-9s %-10s %-10s\n' \
403+
"$jobid" "$name" "$node" "$state" "$elapsed" "$limit"
404+
done <<< "$lines"
405+
echo 1>&2 ""
406+
fi
407+
408+
echo 1>&2 "To reattach to an existing session:"
409+
local jobids
410+
jobids=$(squeue --me --partition=interactive --states=RUNNING --noheader --Format=JobID 2>/dev/null | xargs)
411+
for jid in $jobids; do
412+
echo 1>&2 " sinteractive --attach $jid"
413+
done
414+
echo 1>&2 ""
415+
echo 1>&2 "To free a slot, cancel a session:"
416+
jobids=$(squeue --me --partition=interactive --states=RUNNING,PENDING --noheader --Format=JobID 2>/dev/null | xargs)
417+
for jid in $jobids; do
418+
echo 1>&2 " scancel $jid"
419+
done
420+
echo 1>&2 ""
421+
return 1
422+
fi
423+
424+
return 0
425+
}
426+
284427
function reattach {
285428
local jobid=$1
286429
local sock="sinteractive-${jobid}"

0 commit comments

Comments
 (0)