scrun(1) Slurm Commands scrun(1) (NAME) scrun - OCI Slurm. (SYNOPSIS) (Create Operation) scrun [GLOBAL OPTIONS...] create [CREATE OPTIONS] container-id . (Start Operation) scrun [GLOBAL OPTIONS...] start job. (Query State Operation) scrun [GLOBAL OPTIONS...] state JSON OCI . (Kill Operation) scrun [GLOBAL OPTIONS...] kill [signal] (: SIGTERM) . (Delete Operation) scrun [GLOBAL OPTIONS...] delete [DELETE OPTIONS] . OCI container-id : https://github.com/opencontainers/runtime-spec/blob/main/runtime.md scrun crun runc DOCKER podman . crun runc . (DESCRIPTION) scrun OCI Slurm . DOCKER podman Slurm job . scrun OCI STDIO Slurm . Slurm oci.conf(5) . scrun OCI image : https://github.com/opencontainers/image-spec/blob/main/spec.md (RETURN VALUE) scrun 0 . scrun . (GLOBAL OPTIONS) --cgroup-manager . --debug (debug). -f slurm.conf . : sysconfdir configure --usage scrun --log-format= . "json" "text" . : text --root= spool . tmpfs . : /run/user/{user_id}/scrun/ --rootless . scrun (rootless) . --systemd-cgroup . -v . -v . -V, --version . -b , --bundle= bundle. : --console-socket= AF_UNIX (master) . : --no-pivot . --no-new-keyring . --pid-file= (PID). : --preserve-fds . (DELETE OPTIONS) --force . . (INPUT ENVIRONMENT VARIABLES) SCRUN_DEBUG= (logging). SCRUN_STDERR_DEBUG= . SCRUN_SYSLOG_DEBUG= syslog. SCRUN_FILE_DEBUG= . (JOB INPUT ENVIRONMENT VARIABLES) SCRUN_ACCOUNT SLURM_ACCOUNT srun(1) . SCRUN_ACCTG_FREQ SLURM_ACCTG_FREQ srun(1) . SCRUN_BURST_BUFFER SLURM_BURST_BUFFER srun(1) . SCRUN_CLUSTER_CONSTRAINT SLURM_CLUSTER_CONSTRAINT srun(1) . SCRUN_CLUSTERS SLURM_CLUSTERS srun(1) . SCRUN_CONSTRAINT SLURM_CONSTRAINT srun(1) . SLURM_CORE_SPEC SLURM_ACCOUNT srun(1) . SCRUN_CPU_BIND SLURM_CPU_BIND srun(1) . SCRUN_CPU_FREQ_REQ SLURM_CPU_FREQ_REQ srun(1) . SCRUN_CPUS_PER_GPU SLURM_CPUS_PER_GPU srun(1) . SCRUN_CPUS_PER_TASK SRUN_CPUS_PER_TASK srun(1) . SCRUN_DELAY_BOOT SLURM_DELAY_BOOT srun(1) . SCRUN_DEPENDENCY SLURM_DEPENDENCY srun(1) . SCRUN_DISTRIBUTION SLURM_DISTRIBUTION srun(1) . SCRUN_EPILOG SLURM_EPILOG srun(1) . SCRUN_EXACT SLURM_EXACT srun(1) . SCRUN_EXCLUSIVE SLURM_EXCLUSIVE srun(1) . SCRUN_GPU_BIND SLURM_GPU_BIND srun(1) . SCRUN_GPU_FREQ SLURM_GPU_FREQ srun(1) . SCRUN_GPUS SLURM_GPUS srun(1) . SCRUN_GPUS_PER_NODE SLURM_GPUS_PER_NODE srun(1) . SCRUN_GPUS_PER_SOCKET SLURM_GPUS_PER_SOCKET salloc(1) . SCRUN_GPUS_PER_TASK SLURM_GPUS_PER_TASK srun(1) . SCRUN_GRES_FLAGS SLURM_GRES_FLAGS srun(1) . SCRUN_GRES SLURM_GRES srun(1) . SCRUN_HINT SLURM_HIST srun(1) . SCRUN_JOB_NAME SLURM_JOB_NAME srun(1) . SCRUN_JOB_NODELIST SLURM_JOB_NODELIST srun(1) . SCRUN_JOB_NUM_NODES SLURM_JOB_NUM_NODES srun(1) . SCRUN_LABELIO SLURM_LABELIO srun(1) . SCRUN_MEM_BIND SLURM_MEM_BIND srun(1) . SCRUN_MEM_PER_CPU SLURM_MEM_PER_CPU srun(1) . SCRUN_MEM_PER_GPU SLURM_MEM_PER_GPU srun(1) . SCRUN_MEM_PER_NODE SLURM_MEM_PER_NODE srun(1) . SCRUN_MPI_TYPE SLURM_MPI_TYPE srun(1) . SCRUN_NCORES_PER_SOCKET SLURM_NCORES_PER_SOCKET srun(1) . SCRUN_NETWORK SLURM_NETWORK srun(1) . SCRUN_NSOCKETS_PER_NODE SLURM_NSOCKETS_PER_NODE srun(1) . SCRUN_NTASKS SLURM_NTASKS srun(1) . SCRUN_NTASKS_PER_CORE SLURM_NTASKS_PER_CORE srun(1) . SCRUN_NTASKS_PER_GPU SLURM_NTASKS_PER_GPU srun(1) . SCRUN_NTASKS_PER_NODE SLURM_NTASKS_PER_NODE srun(1) . SCRUN_NTASKS_PER_TRES SLURM_NTASKS_PER_TRES srun(1) . SCRUN_OPEN_MODE SLURM_MODE srun(1) . SCRUN_OVERCOMMIT SLURM_OVERCOMMIT srun(1) . SCRUN_OVERLAP SLURM_OVERLAP srun(1) . SCRUN_PARTITION SLURM_PARTITION srun(1) . SCRUN_POWER SLURM_POWER srun(1) . SCRUN_PROFILE SLURM_PROFILE srun(1) . SCRUN_PROLOG SLURM_PROLOG srun(1) . SCRUN_QOS SLURM_QOS srun(1) . SCRUN_REMOTE_CWD SLURM_REMOTE_CWD srun(1) . SCRUN_REQ_SWITCH SLURM_REQ_SWITCH srun(1) . SCRUN_RESERVATION SLURM_RESERVATION srun(1) . SCRUN_SIGNAL SLURM_SIGNAL srun(1) . SCRUN_SLURMD_DEBUG SLURMD_DEBUG srun(1) . SCRUN_SPREAD_JOB SLURM_SPREAD_JOB srun(1) . SCRUN_TASK_EPILOG SLURM_TASK_EPILOG srun(1) . SCRUN_TASK_PROLOG SLURM_TASK_PROLOG srun(1). SCRUN_THREAD_SPEC SLURM_THREAD_SPEC srun(1). SCRUN_THREADS_PER_CORE SLURM_THREADS_PER_CORE srun(1). SCRUN_THREADS SLURM_THREADS srun(1). SCRUN_TIMELIMIT SLURM_TIMELIMIT srun(1). SCRUN_TRES_BIND --tres-bind SCRUN_TRES_PER_TASK SLURM_TRES_PER_TASK srun(1). SCRUN_UNBUFFEREDIO SLURM_UNBUFFEREDIO srun(1). SCRUN_USE_MIN_NODES SLURM_USE_MIN_NODES srun(1). SCRUN_WAIT4SWITCH SLURM_WAIT4SWITCH srun(1). SCRUN_WCKEY SLURM_WCKEY srun(1). SCRUN_WORKING_DIR SLURM_WORKING_DIR srun(1). (OUTPUT ENVIRONMENT VARIABLES) SCRUN_OCI_VERSION OCI . SCRUN_CONTAINER_ID container_id create . SCRUN_PID (PID) . SCRUN_BUNDLE . SCRUN_SUBMISSION_BUNDLE Lua. SCRUN_ANNOTATION_* config.json . SCRUN_PID_FILE pid PID scrun . SCRUN_SOCKET scrun. SCRUN_SPOOL_DIR . deletion . SCRUN_SUBMISSION_CONFIG_FILE config.json (submission). SCRUN_USER create . SCRUN_USER_ID (ID) create . SCRUN_GROUP create . SCRUN_GROUP_ID (ID) create . SCRUN_ROOT --root. SCRUN_ROOTFS_PATH . SCRUN_SUBMISSION_ROOTFS_PATH (submission). SCRUN_LOG_FILE (log) scrun create. SCRUN_LOG_FORMAT (log) create. SLURM_*_HET_GROUP_# (heterogeneous) . SLURM_CLUSTER_NAME . SLURM_CONTAINER OCI (OCI Bundle) . SLURM_CONTAINER_ID OCI (OCI id) . SLURM_CPUS_PER_GPU CPU GPU . SLURM_CPUS_PER_TASK CPU (task). SLURM_DIST_PLANESIZE (plane distribution size). . SLURM_DISTRIBUTION . SLURM_GPU_BIND (binding) GPU. SLURM_GPU_FREQ () GPU. SLURM_GPUS GPU . SLURM_GPUS_PER_NODE GPU . SLURM_GPUS_PER_SOCKET GPU . SLURM_GPUS_PER_TASK GPU . SLURM_HET_SIZE . SLURM_JOB_ACCOUNT . SLURM_JOB_CPUS_PER_NODE CPU CPU_count[(xnumber_of_nodes)][,CPU_count [(xnumber_of_nodes)] ...]. : SLURM_JOB_CPUS_PER_NODE='72(x2),36' ( SLURM_JOB_NODELIST ) . : select/linear CPU . select/cons_tres CPU . SLURM_JOB_END_TIME (UNIX timestamp) . SLURM_JOB_GPUS GPU (global GPU IDs) GPU . GPU cgroup task/cgroup . (batch) (interactive) . SLURM_JOB_ID . SLURM_JOB_NODELIST . SLURM_JOB_NUM_NODES . SLURM_JOB_PARTITION . SLURM_JOB_QOS (QOS) . SLURM_JOB_RESERVATION (advanced reservation) . SLURM_JOB_START_TIME (UNIX timestamp) . SLURM_MEM_BIND (Memory binding). SLURM_MEM_BIND_LIST (bit mask) . SLURM_MEM_BIND_PREFER SLURM_MEM_BIND prefer "prefer" . SLURM_MEM_BIND_TYPE SLURM_MEM_BIND . "none" "rank" "map_mem:" "mask_mem:" "local". SLURM_MEM_BIND_VERBOSE SLURM_MEM_BIND verbose "verbose" . "quiet" . SLURM_MEM_PER_CPU CPU . SLURM_MEM_PER_GPU GPU . SLURM_MEM_PER_NODE . SLURM_NTASKS . SLURM_NTASKS_PER_CORE ntasks . SLURM_NTASKS_PER_GPU ntasks GPU. SLURM_NTASKS_PER_NODE ntasks . SLURM_NTASKS_PER_SOCKET ntasks . SLURM_OVERCOMMIT (Overcommit). SLURM_PROFILE acct_gather_profile . SLURM_SHARDS_ON_NODE GPU Shard . SLURM_SUBMIT_HOST scrun . SLURM_TASKS_PER_NODE . SLURM_JOB_NODELIST . <<(x#)>> <<#>> . <> . SLURM_THREADS_PER_CORE --threads-per-core SCRUN_THREADS_PER_CORE . --threads-per-core SCRUN_THREADS_PER_CORE . srun . SLURM_TRES_PER_TASK --tres-per-task . --cpus-per-task --gpus-per-task SLURM_TRES_PER_TASK --tres-per-task . SCRUN.LUA /etc/slurm/scrun.lua scrun . scrun.lua lua ..SS " (Required functions)" . o function slurm_scrun_stage_in(id, bundle, spool_dir, config_file, job_id, user_id, group_id, job_env) (job allocation) (stage in) () . SLURM.success . () oci.conf(1) . (block) ( wall time). id (Container ID) bundle OCI bundle spool_dir config_file config.json job_id jobid user_id . lua user namespace root(0) . group_id . lua user namespace root(0) . job_env = (Key=Value) . o function slurm_scrun_stage_out(id, bundle, orig_bundle, root_path, orig_root_path, spool_dir, config_file, jobid, user_id, group_id) (container step) (stage out) . SLURM.success . () . (block) ( wall time). id (Container ID) bundle OCI bundle orig_bundle OCI bundle set_bundle_path(). root_path . orig_root_path set_root_path(). spool_dir config_file config.json job_id jobid user_id . lua user namespace root(0) . group_id . lua user namespace root(0) . Lua . o slurm.set_bundle_path(PATH) scrun PATH OCI . (job nodes) . o slurm.set_root_path(PATH) scrun PATH . . #/root/path config.json . o STATUS,OUTPUT = slurm.remote_command(SCRIPT) SCRIPT (job step) . STATUS stdio OUTPUT . SCRIPT . o STATUS,OUTPUT = slurm.allocator_command(SCRIPT) SCRIPT (forked) scrun. STATUS stdio OUTPUT . SCRIPT . o slurm.log(MSG, LEVEL) MSG LEVEL. LEVEL [0, 4] . o slurm.error(MSG) MSG. o slurm.log_error(MSG) MSG. o slurm.log_info(MSG) MSG INFO. o slurm.log_verbose(MSG) MSG VERBOSE. o slurm.log_verbose(MSG) MSG VERBOSE. o slurm.log_debug(MSG) MSG DEBUG. o slurm.log_debug2(MSG) MSG DEBUG2. o slurm.log_debug3(MSG) MSG DEBUG3. o slurm.log_debug4(MSG) MSG DEBUG4. o MINUTES = slurm.time_str2mins(TIME_STRING) TIME_STRING MINUTES. : o days-[hours[:minutes[:seconds]]] o hours:minutes:seconds o minutes[:seconds] o -1 o INFINITE o UNLIMITED rsync: docker podman (stage) . config.json crun runc . rsync scratch_path . : JSON liblua Slurm . scrun.lua JSON lua Slurm . local open = io.open local scratch_path = "/run/user" local function read_file(path) local file = open(path, "rb") if not file then return nil end local content = file:read "*all" file:close() return content end local function write_file(path, contents) local file = open(path, "wb") if not file then return nil end file:write(contents) file:close() return end function slurm_scrun_stage_in(id, bundle, spool_dir, config_file, job_id, user_id, group_id, job_env) slurm.log_debug(string.format("stage_in(%s, %s, %s, %s, %d, %d, %d)", id, bundle, spool_dir, config_file, job_id, user_id, group_id)) local status, output, user, rc local config = slurm.from_json(read_file(config_file)) local src_rootfs = config["root"]["path"] rc, user = slurm.allocator_command(string.format("id -un %d", user_id)) user = string.gsub(user, "%s+", "") local root = scratch_path.."/"..math.floor(user_id).."/slurm/scrun/" local dst_bundle = root.."/"..id.."/" local dst_config = root.."/"..id.."/config.json" local dst_rootfs = root.."/"..id.."/rootfs/" if string.sub(src_rootfs, 1, 1) ~= "/" then -- always use absolute path src_rootfs = string.format("%s/%s", bundle, src_rootfs) end status, output = slurm.allocator_command("mkdir -p "..dst_rootfs) if (status ~= 0) then slurm.log_info(string.format("mkdir(%s) failed %u: %s", dst_rootfs, status, output)) return slurm.ERROR end status, output = slurm.allocator_command(string.format("/usr/bin/env rsync --exclude sys --exclude proc --numeric-ids --delete-after --ignore-errors --stats -a -- %s/ %s/", src_rootfs, dst_rootfs)) if (status ~= 0) then -- rsync can fail due to permissions which may not matter slurm.log_info(string.format("WARNING: rsync failed: %s", output)) end slurm.set_bundle_path(dst_bundle) slurm.set_root_path(dst_rootfs) config["root"]["path"] = dst_rootfs -- Always force user namespace support in container or runc will reject local process_user_id = 0 local process_group_id = 0 if ((config["process"] ~= nil) and (config["process"]["user"] ~= nil)) then -- resolve out user in the container if (config["process"]["user"]["uid"] ~= nil) then process_user_id=config["process"]["user"]["uid"] else process_user_id=0 end -- resolve out group in the container if (config["process"]["user"]["gid"] ~= nil) then process_group_id=config["process"]["user"]["gid"] else process_group_id=0 end -- purge additionalGids as they are not supported in rootless if (config["process"]["user"]["additionalGids"] ~= nil) then config["process"]["user"]["additionalGids"] = nil end end if (config["linux"] ~= nil) then -- force user namespace to always be defined for rootless mode local found = false if (config["linux"]["namespaces"] == nil) then config["linux"]["namespaces"] = {} else for _, namespace in ipairs(config["linux"]["namespaces"]) do if (namespace["type"] == "user") then found=true break end end end if (found == false) then table.insert(config["linux"]["namespaces"], {type= "user"}) end -- Provide default user map as root if one not provided if (true or config["linux"]["uidMappings"] == nil) then config["linux"]["uidMappings"] = {{containerID=process_user_id, hostID=math.floor(user_id), size=1}} end -- Provide default group map as root if one not provided -- mappings fail with build??? if (true or config["linux"]["gidMappings"] == nil) then config["linux"]["gidMappings"] = {{containerID=process_group_id, hostID=math.floor(group_id), size=1}} end -- disable trying to use a specific cgroup config["linux"]["cgroupsPath"] = nil end if (config["mounts"] ~= nil) then -- Find and remove any user/group settings in mounts for _, mount in ipairs(config["mounts"]) do local opts = {} if (mount["options"] ~= nil) then for _, opt in ipairs(mount["options"]) do if ((string.sub(opt, 1, 4) ~= "gid=") and (string.sub(opt, 1, 4) ~= "uid=")) then table.insert(opts, opt) end end end if (opts ~= nil and #opts > 0) then mount["options"] = opts else mount["options"] = nil end end -- Remove all bind mounts by copying files into rootfs local mounts = {} for i, mount in ipairs(config["mounts"]) do if ((mount["type"] ~= nil) and (mount["type"] == "bind") and (string.sub(mount["source"], 1, 4) ~= "/sys") and (string.sub(mount["source"], 1, 5) ~= "/proc")) then status, output = slurm.allocator_command(string.format("/usr/bin/env rsync --numeric-ids --ignore-errors --stats -a -- %s %s", mount["source"], dst_rootfs..mount["destination"])) if (status ~= 0) then -- rsync can fail due to permissions which may not matter slurm.log_info("rsync failed") end else table.insert(mounts, mount) end end config["mounts"] = mounts end -- Force version to one compatible with older runc/crun at risk of new features silently failing config["ociVersion"] = "1.0.0" -- Merge in Job environment into container -- this is optional! if (config["process"]["env"] == nil) then config["process"]["env"] = {} end for _, env in ipairs(job_env) do table.insert(config["process"]["env"], env) end -- Remove all prestart hooks to squash any networking attempts if ((config["hooks"] ~= nil) and (config["hooks"]["prestart"] ~= nil)) then config["hooks"]["prestart"] = nil end -- Remove all rlimits if ((config["process"] ~= nil) and (config["process"]["rlimits"] ~= nil)) then config["process"]["rlimits"] = nil end write_file(dst_config, slurm.to_json(config)) slurm.log_info("created: "..dst_config) return slurm.SUCCESS end function slurm_scrun_stage_out(id, bundle, orig_bundle, root_path, orig_root_path, spool_dir, config_file, jobid, user_id, group_id) if (root_path == nil) then root_path = "" end slurm.log_debug(string.format("stage_out(%s, %s, %s, %s, %s, %s, %s, %d, %d, %d)", id, bundle, orig_bundle, root_path, orig_root_path, spool_dir, config_file, jobid, user_id, group_id)) if (bundle == orig_bundle) then slurm.log_info(string.format("skipping stage_out as bundle=orig_bundle=%s", bundle)) return slurm.SUCCESS end status, output = slurm.allocator_command(string.format("/usr/bin/env rsync --numeric-ids --delete-after --ignore-errors --stats -a -- %s/ %s/", root_path, orig_root_path)) if (status ~= 0) then -- rsync can fail due to permissions which may not matter slurm.log_info("rsync failed") else -- cleanup temporary after they have been synced backed to source slurm.allocator_command(string.format("/usr/bin/rm --preserve-root=all --one-file-system -dr -- %s", bundle)) end return slurm.SUCCESS end slurm.log_info("initialized scrun.lua") return slurm.SUCCESS SIGINT ( ) . SIGCHLD anchor . (COPYING) (C) 2023 SchedMD LLC. Slurm . . Slurm << >> ( ) . Slurm . << >> . (SEE ALSO) slurm(1) oci.conf(5) srun(1) crun runc DOCKER podman Slurm 26.05 Slurm Commands scrun(1)