A job script tells Slurm what your job needs (cores, memory, time, queue) and what to run. Write it once, submit it with sbatch, and Slurm runs it on a compute node when resources are free. This page gives you a template to copy, explains each part, and lists the options you'll use most.

On this page: The four parts ยท Template ยท Asking for resources ยท Directive reference ยท Useful variables ยท Dependencies ยท Make scripts safer ยท Troubleshooting

Shortcut: the job script builder asks a few questions and writes the script for you. Remember to run module load slurm before using sbatch.

The four parts of a job script

  1. Shebang line: #!/bin/bash, so the script runs in bash.
  2. #SBATCH lines: what the job needs. Slurm reads these; bash treats them as comments.
  3. Environment setup: load modules and set variables.
  4. The work: the commands that actually run.

Template

#!/bin/bash

# --- Job identification ---
#SBATCH --job-name=my_job
#SBATCH --output=%x_%j.out            # %x = job name, %j = job ID
#SBATCH --error=%x_%j.err

# --- Resources ---
#SBATCH --partition=short-40core
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=40
#SBATCH --time=02:00:00               # hh:mm:ss

# --- Optional: email when it ends or fails ---
#SBATCH --mail-type=END,FAIL
#SBATCH --mail-user=<you>@stonybrook.edu

# --- Environment setup ---
module purge
module load intel/oneAPI/2022.2
module load compiler/latest
module load mpi/latest
export OMP_NUM_THREADS=1

echo "Job $SLURM_JOB_ID on $SLURM_JOB_NODELIST, $SLURM_NTASKS tasks, started $(date)"

# --- The work ---
cd $SLURM_SUBMIT_DIR
mpirun ./my_app input.dat > computation.log

echo "Finished $(date)"

Submit it and check on it:

sbatch my_job.slurm
squeue -u $USER

Ready-made scripts for serial, multi-threaded, MPI, GPU, and array jobs are in Example jobs.

Asking for the right resources

  • Pick the queue first. The queue decides the node type and the maximum run time. See the queue selection guide.
  • Whole node or part of one? Queues without -shared give you whole nodes, with all their memory. For small jobs, use a shared queue and set --mem.
  • Tasks vs. CPUs per task. Use --ntasks for MPI processes and --cpus-per-task for threads (OpenMP, Python multiprocessing). Match OMP_NUM_THREADS to $SLURM_CPUS_PER_TASK.
  • Time. Ask for a realistic limit with some margin. Shorter requests often start sooner; if the job runs past its limit, Slurm stops it.
  • Check afterward. seff <jobid> shows how much CPU and memory you really used, so you can ask for less next time.

Directive reference

DirectiveWhat it setsExample
-p, --partitionQueue#SBATCH -p short-40core
-N, --nodesNumber of nodes#SBATCH -N 2
-n, --ntasksTotal tasks (e.g. MPI ranks)#SBATCH -n 80
--ntasks-per-nodeTasks on each node#SBATCH --ntasks-per-node=40
-c, --cpus-per-taskCPUs for each task (threads)#SBATCH -c 8
--memMemory per node#SBATCH --mem=64GB
--mem-per-cpuMemory per CPU#SBATCH --mem-per-cpu=2GB
-t, --timeTime limit#SBATCH -t 02:30:00
-J, --job-nameJob name#SBATCH -J my_job
-o, --outputFile for normal output#SBATCH -o job_%j.out
-e, --errorFile for error output#SBATCH -e job_%j.err
--gresGPUs and other resources#SBATCH --gres=gpu:2
--arrayJob array indices#SBATCH --array=1-100
--mail-type, --mail-userEmail notices#SBATCH --mail-type=END,FAIL

Useful variables inside a job

VariableHolds
$SLURM_JOB_IDThe job ID
$SLURM_SUBMIT_DIRThe folder you ran sbatch from
$SLURM_JOB_NODELISTThe nodes the job is running on
$SLURM_NTASKSTotal number of tasks
$SLURM_CPUS_PER_TASKCPUs given to each task
$SLURM_ARRAY_TASK_IDThis task's index in a job array

Run jobs in order (dependencies)

For work in steps, such as preprocessing, then analysis, then plotting, you can submit every step at once and have each one wait for the one before it. Slurm holds the later jobs until their condition is met.

# Submit the first step and keep its job ID
jid=$(sbatch --parsable step1.slurm)

# Start step 2 only if step 1 finishes successfully
sbatch --dependency=afterok:$jid step2.slurm
ConditionThe new job starts once the earlier job has
afterok:<jobid>finished successfully (exit code 0)
afternotok:<jobid>failed, which is handy for a cleanup or alert step
afterany:<jobid>ended, whatever the outcome
after:<jobid>started running

You can wait on several jobs at once, as in afterok:1234:1235. If a condition can never be met (step 1 failed and step 2 needed afterok), the waiting job stays in the queue with the reason DependencyNeverSatisfied. Cancel it with scancel <jobid>.

Make scripts safer and easier to debug

# Stop at the first error instead of carrying on
set -e

# Check the input exists before doing any work
if [ ! -f "input.dat" ]; then
    echo "ERROR: input.dat not found"
    exit 1
fi

# Time the main step
start=$(date +%s)
mpirun ./my_app input.dat
echo "Computation took $(( $(date +%s) - start )) seconds"
  • Start with module purge so modules left over from your login session don't interfere.
  • Load the same modules you compiled with.
  • Test small first: a short run in debug-40core, or an interactive session, before a big submission.
  • Keep a template for each kind of job you run often.

Troubleshooting

"sbatch: command not found"

Run module load slurm first.

"Batch job submission failed: Requested node configuration is not available"

You asked for more cores, memory, or GPUs than a node in that queue has, or used a queue that isn't reachable from your login node. Compare your request with the queue tables, and see which login node reaches which queues.

My job ended early with "TIME LIMIT" or "DUE TO TIME LIMIT"

It ran past its --time. Ask for more time, move to a longer queue, or save progress (checkpoint) so you can restart.

"Out of memory" or "oom-kill"

The job used more memory than it asked for. Raise --mem (on shared queues) or use more nodes. seff <jobid> shows the peak memory used.

Windows line endings: "/bin/bash^M: bad interpreter"

The script was saved on Windows. Convert it on the cluster with:

sed -i 's/\r$//' my_job.slurm

More commands for watching and changing jobs are in Managing jobs and the cheat sheet.

Applies to All clusters