Euler is ETH Zurich's shared research-computing service. Slurm is the scheduler that accepts a job and runs it on a compute node; the login node is only the entry point used to prepare and control that work.
Goal: submit, monitor, and account for a tiny CPU job without computing on a login node.
Prerequisites: the public-key login test passes, the small
Euler Python environment is ready,
the Euler CPU Track is started, and my_share_info
lists the intended account.
New to text commands? Read how to open a terminal and run one command before using a command block. It explains the labels used below and what to copy.
Execution context: all commands run on an Euler login node - Bash.
Follow the current first-job mission for the normal browser route. This is its standalone text companion, not a second job to submit: create -> inspect -> submit once -> observe -> account.
1. Confirm Context And Share#
hostname
my_share_info
pwd
Expected result: the hostname begins with an Euler login-node name and
es_fuge appears for IDEAL Lab users.
2. Create The Tiny Script#
(
set -eu
work_dir="$HOME/passport-euler"
script="$work_dir/first-job.slurm"
mkdir -p "$work_dir/logs"
tmp="$(mktemp "$work_dir/.first-job.XXXXXX")"
trap 'if [ -n "${tmp:-}" ]; then rm -f "$tmp"; fi' EXIT
cat > "$tmp" <<'EOF'
#!/usr/bin/env bash
#SBATCH --job-name=passport-cpu
#SBATCH --account=es_fuge
#SBATCH --time=00:02:00
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=1
#SBATCH --mem-per-cpu=1G
#SBATCH --output=logs/%x_%j.out
#SBATCH --error=logs/%x_%j.err
set -euo pipefail
module purge
module load stack/2024-06 python/3.11.6
venv="$HOME/passport-euler/venvs/passport-python"
[ -x "$venv/bin/python" ] || {
printf 'STOP: complete the Euler Python environment mission first.\n' >&2
exit 1
}
. "$venv/bin/activate"
python - <<'PYTHON'
import os
import pathlib
import platform
import socket
import sys
expected = pathlib.Path.home() / "passport-euler" / "venvs" / "passport-python"
if pathlib.Path(sys.prefix) != expected or platform.python_version() != "3.11.6":
raise SystemExit("STOP: unexpected Python environment")
print(f"job_id={os.environ['SLURM_JOB_ID']}")
print(f"host={socket.gethostname()}")
print(f"cpus={os.environ['SLURM_CPUS_PER_TASK']}")
print("python_environment=passport-python")
for number in range(1, 6):
print(f"{number} squared is {number * number}")
PYTHON
EOF
if [ -e "$script" ]; then
cmp -s "$tmp" "$script" || {
printf 'STOP: %s already exists with different content.\n' "$script" >&2
exit 1
}
printf 'existing-script-ok\n'
else
mv "$tmp" "$script"
tmp=''
printf 'created-script-ok\n'
fi
cd "$work_dir"
bash -n first-job.slurm
sed -n '1,100p' first-job.slurm
)
This intentionally requests one CPU, 1 GiB per CPU, two minutes, and no GPU.
The command prints created-script-ok or existing-script-ok before showing
the script. Its displayed last line is PYTHON: EOF and the lines after it
finish creating the file and are not part of the displayed script. This step
does not submit a job, so an empty squeue is normal. Check the script before
continuing to submit it in the next section.
3. Submit And Monitor#
(
set -eu
cd "$HOME/passport-euler"
id_file="$HOME/passport-euler/first-job.id"
if [ -e "$id_file" ]; then
[ -s "$id_file" ] || {
printf 'STOP: %s is empty. Ask for help before submitting.\n' "$id_file" >&2
exit 1
}
job_id="$(cat "$id_file")"
case "$job_id" in
''|*[^0-9]*) printf 'STOP: stored job ID is invalid.\n' >&2; exit 1 ;;
esac
printf 'Existing job, not resubmitted: %s\n' "$job_id"
else
submission="$(sbatch --parsable first-job.slurm)"
job_id="${submission%%;*}"
case "$job_id" in
''|*[^0-9]*) printf 'STOP: sbatch did not return a numeric job ID.\n' >&2; exit 1 ;;
esac
printf '%s\n' "$job_id" > "$id_file"
chmod 600 "$id_file"
printf 'Submitted job: %s\n' "$job_id"
fi
squeue -j "$job_id"
)
Stop The Recorded Job If Needed#
Only if the script or request is wrong, stop the recorded job. Do not cancel a completed successful job merely for practice. Verify the stored ID belongs to this exercise and return to the interrupted mission afterwards. If its record is missing or ambiguous, ask for help before acting.
If you notice an error in the script or request:
job_id="$(cat "$HOME/passport-euler/first-job.id")"
scancel "$job_id"
4. Inspect Output And Accounting#
After the job leaves squeue:
job_id="$(cat "$HOME/passport-euler/first-job.id")"
cd "$HOME/passport-euler"
cat "logs/passport-cpu_${job_id}.out"
cat "logs/passport-cpu_${job_id}.err"
sacct -j "$job_id" \
--format=JobID,JobName%20,Account%40,State,ExitCode,Elapsed,AllocCPUS,ReqMem,MaxRSS
seff "$job_id"
The error file should be empty, the output should contain
python_environment=passport-python, and the main job should complete.
Accounting may include .batch and .extern steps; that is normal.
The main job's Account column can show normal/es_fuge; Account%40
prevents its name being shortened to a value such as normal/es+.
Verification#
- The output hostname is a compute node, not the login node.
- The output contains
python_environment=passport-python. - The main job state is
COMPLETEDwith a successful exit code. - Exactly one CPU and no GPU were requested.
- You can explain
Elapsed,ReqMem,MaxRSS, and theseffsummary.
Common Failures And Safe Recovery#
- Invalid account: stop and confirm
my_share_info; do not guess an account. - Job pending: inspect
myjobs -j "$job_id"; do not submit duplicates. - Error log not empty: read the first meaningful error before changing resources.
- Accounting temporarily blank: wait briefly and rerun
sacct.
Understand Before Accepting AI Output#
- I read the script before submitting it.
- I recorded the real job ID.
- I know how to cancel it.
- I personally inspected output and accounting.
Evidence#
Keep the script, ID, logs and interpretation in your private working notes. The Passport submits only its declared answers and sanitized receipts; it does not collect a free-form interpretation or public job log. Never put the real ID, username, private path or unrelated job history in public evidence.
Ask For Help When#
The account is missing, the job cannot enter the queue, the state/exit code is unclear, or the login node was used accidentally for computation.