#!/bin/bash #Need bash for arrays # #--------------------------------------------------------- # This script is under version control in git repository #git@gitlab.umd.edu:dit-perl-packages/hpcc-pdb-packages/assorted-slurm-scripts.git # # Please make all edits to git repo #--------------------------------------------------------- VERSION="1.0" #Set defaults FLDDELIM=':' RECDELIM="\n" #No default for MODE MODE= usage() { cat - >&2 < /dev/null if [ $? -eq 0 ]; then #There is a (x pattern in rec #Split into ntasks and count ntasks=`echo $rec | sed -e 's/(x.*$//'` count=`echo $rec | sed -e 's/^.*(x//' -e 's/)$//'` else #No (x pattern. #ntasks = rec #and count = 1 ntasks="$rec" count=1 fi #Print out ntasks count times for i in `seq 1 $count` do echo $ntasks done done } #This defines a bash function to expand SLURM_JOB_NODELIST from its #compact form (using ranges, etc) to a simple list. #Basically, just invokes scontrol show hostnames expand_hostlist() { HLIST="${SLURM_JOB_NODELIST}" if [ "x$HLIST" = "x" ]; then #Try deprecated SLURM_NODELIST HLIST="${SLURM_NODELIST}" fi if [ "x$HLIST" = "x" ]; then echo >&2 "ERROR: SLURM_JOB_NODELIST not found" echo >&2 "This script should only be run within" echo >&2 "a Slurm job" exit 1 fi hostnames=( `scontrol show hostnames $HLIST` ) echo "${hostnames[@]}" } #This defines a bash function which uses both SLURM_TASKS_PER_NODE #and SLURM_JOB_NODELIST and returns a list of hostnames for the #nodes allocated to this job, with each hostname occuring once for #each task assigned to the node. #Usage: hostlist=`expand_tasks_hosts` expand_tasks_hosts() { #First convert SLURM_JOB_NODELIST into an array of hostnames hostnames=( `expand_hostlist` ) #And convert SLURM_TASKS_PER_NODE into an array of task counts taskcounts=( `expand_tasklist` ) #Get the count of hostnames, less one n="${#hostnames[*]}" n=$(( n - 1 )) #Loop over the hostnames and taskcounts arrays for i in `seq 0 $n` do #Get the i-th hostname/taskcount host="${hostnames[$i]}" count="${taskcounts[$i]}" #Output each hostname as many times as it has tasks for j in `seq 1 $count` do echo "$host" done done } #----------------- Main ----------------- #Can't use getopts because we want to ignore some options while getopts :hMRf:r:m: arg do case $arg in h) usage exit 0 ;; M) man_usage exit 0 ;; R) rawman_usage exit 0 ;; V) echo "$VERSION" exit 0 ;; r) RECDELIM="$OPTARG" ;; f) FLDDELIM="$OPTARG" ;; m) MODE="$OPTARG" ;; *) usage echo >&2 echo "Illegal option -$OPTARG, aborting." >&2 exit 1 ;; esac done COUNT=$(( OPTIND - 1 )) shift $COUNT if [ "x$MODE" = "x" ]; then usage echo >&2 echo "You must supply a value for MODE, aborting." >&2 exit 1 fi case $MODE in hostnames) hostnames=( `expand_hostlist` ) delim="" for hostname in "${hostnames[@]}" do echo -n -e "$delim" delim="$RECDELIM" echo -n -e "${hostname}" done echo -n -e "\n" exit 0 ;; counts) taskcounts=( `expand_tasklist` ) delim="" for taskcount in "${taskcounts[@]}" do echo -n -e "$delim" delim="$RECDELIM" echo -n -e "${taskcount}" done echo -n -e "\n" exit 0 ;; hosts_by_tasks) hostlist=( `expand_tasks_hosts` ) delim="" for hostname in "${hostlist[@]}" do echo -n -e "$delim" delim="$RECDELIM" echo -n -e "${hostname}" done echo -n -e "\n" exit 0 ;; host_count) hostlist=( `expand_hostlist` ) taskcounts=( `expand_tasklist` ) n="${#hostlist[*]}" n=$(( n - 1 )) delim="" for i in `seq 0 $n` do #Get the i-th hostname/taskcount host="${hostlist[$i]}" count="${taskcounts[$i]}" echo -n -e "$delim" delim="$RECDELIM" echo -n -e "${host}${FLDDELIM}${count}" done echo -n -e "\n" exit 0 ;; *) usage echo >&2 echo >&2 "ERROR: Unrecognized value '$MODE' for MODE" echo >&2 "Aborting" exit 1 ;; esac