diff --git a/README.md b/README.md index 211bfb0..5e73b2a 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The overall structure is as follow: 2. RServer&CommandlineScreen - A guide to using RServer and the Commandline 3. PureCommandLine - A guide to using pure commandline 4. Slurm - A guide to using our job scheduler. -5. Tools - Contains script for adding SSH aliases for Euclid servers. +5. Tools - Student-written tools for: adding SSH aliases for Euclid servers, checking live usage, checking a program is installed etc. 6. BasicCommands - A collection of simple commands for connecting to the servers. ## Command line use. diff --git a/tools/README.md b/tools/README.md index 5ba79d2..edbbb32 100644 --- a/tools/README.md +++ b/tools/README.md @@ -1,5 +1,7 @@ # Euclid Tools -This folder contains command line tools useful for working with the Euclids. +This folder contains student-written command line tools which you may find useful for working with the Euclids. + +Use at your own risk, and always be careful not to cause any disruption to other users or access machines which you do not have permission to use. The lists of restricted-access and general-use Euclid machines on which these scripts rely were correct as of January 2026. ## Create SSH Aliases To prevent you having to type out `@euclid-.maths.gla.ac.uk` every time, aliases for servers can be added to your SSH config file, usually located at `~/.ssh/config`. @@ -14,3 +16,14 @@ Host euclid-01 # Alias of your choice For Unix/WSL/MacOS, these aliases can be added to your SSH config file using the script located at `tools/euclid-ssh-aliases/create-euclid-aliases.sh`. Use `create-euclid-aliases.sh -h` for help menu. By default aliases will only be created for Euclids with unrestricted access. For Windows, copy the config file you wish to use, use a find-and-replace tool to replace `` with your username, and copy into `~/.ssh/config` (where `~/` specifies your home folder on your machine). + +## Check Installed & Usage +These helper scripts check all public Euclids for the existence of a particular command (check_installed.sh) or the live CPU/Memory/GPU utilisation (usage.sh). + +These can be modified to include other Euclids to which you have access by modifying the "SERVERS" variable in each script. + +To add aliases for these scripts, you can add the following to your `~/.bashrc` file: +```bash +alias euclid-usage='./path/to/ServerInfo/tools/usage.sh' +alias euclid-installed='./path/to/ServerInfo/tools/check_installed.sh' +``` diff --git a/tools/check_installed.sh b/tools/check_installed.sh new file mode 100755 index 0000000..a65b428 --- /dev/null +++ b/tools/check_installed.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# Student-written helper script which uses "command" to check whether a command exists on each of the Euclids. +# Use at own risk, and always be careful not to cause any disruption to other users or access machines which you do not have permission to use. +# Specify --pip to check Python libraries instead of installed applications. + +UNRESTRICTED_SERVERS="01 02 04 05 10 18 19 21 23 25 26 27 28 29 30" +RESTRICTED_SERVERS="03 06 07 08 09 12 17 22 24 32 35 36 37 " +SLURM_SERVERS="13 14 15 16 20 31 33" +RETIRED_SERVERS="11 34" + +SERVERS=$UNRESTRICTED_SERVERS + +cmdToCheck=$1 + +function cleanup { + echo "" +} +trap cleanup EXIT + +if [[ -z $cmdToCheck ]]; then + echo "No command to check installation status specified, exiting." + echo "Usage: ./check_installed.sh " + exit +fi + +while true; do + read -p "Check whether command '$cmdToCheck' exists on the euclid servers? Y/n " yn + case $yn in + [Yy]* ) break;; + [Nn]* ) exit;; + * ) echo "Please answer Y/n.";; + esac +done + +# Run command & save output to temp directory +tmpdir=$(mktemp -d) +if [[ $* == *--pip* ]]; then + cmd="pip list | grep '$cmdToCheck '" +else + cmd="command -v $cmdToCheck" # Command to run on each euclid +fi +for euclid in $SERVERS; do + echo $(if out=$(ssh "euclid-$euclid" -q -o RemoteCommand="$cmd" 2>&1); then + echo "$out" + else + echo "Not installed" + fi + ) > $tmpdir/euclid-$euclid & +done + +# Display outputs: +n_servers=$(echo $SERVERS | wc --words) +while :; do + done_count=0 + for euclid in $SERVERS; do + if [[ -f "$tmpdir/euclid-$euclid" ]]; then + printf "euclid-$euclid: %s\n" "$(tr '\n' ' ' < $tmpdir/euclid-$euclid)" + ((done_count++)) + else + printf "euclid-$euclid:\n" + fi + done + + # Break if all servers have responded + ((done_count == n_servers)) && break + + # Move cursor back to top + printf "\033[${n_servers}A" + + # Wait before re-checking + sleep 0.2 +done + +rm -r "$tmpdir" diff --git a/tools/usage.sh b/tools/usage.sh new file mode 100755 index 0000000..e321e07 --- /dev/null +++ b/tools/usage.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# Usage: usage.sh [euclid ids to check usage of] +# Student-written helper script to check the live CPU/Memory/GPU utilisation of the Euclid servers. +# Use at own risk, and always be careful not to cause any disruption to other users or access machines which you do not have permission to use. + +UNRESTRICTED_SERVERS="01 02 04 05 10 18 19 21 23 25 26 27 28 29 30" +RESTRICTED_SERVERS="03 06 07 08 09 12 17 22 24 32 35 36 37 " +SLURM_SERVERS="13 14 15 16 20 31 33" +RETIRED_SERVERS="11 34" + +SERVERS=$UNRESTRICTED_SERVERS + +if [[ $# > 0 ]]; then + SERVERS="$@" +fi + +# Run command & save output to temp directory +tmpdir=$(mktemp -d) +run_cmd(){ + ssh "euclid-$euclid" -q -o RemoteCommand="$1" +} +for euclid in $SERVERS; do + run_cmd "top -bn 5 -d 0.1 -E M" | grep -e '^%Cpu' -e '^MiB Mem' | tail -n 2 > $tmpdir/euclid-$euclid-cpu-mem & + run_cmd "lscpu" > $tmpdir/euclid-$euclid-lscpu & + run_cmd "if [[ \$(command -v nvidia-smi) ]]; then nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits; else echo '-1'; fi" > $tmpdir/euclid-$euclid-gpu & # Saves each GPU percentage to a newline +done + +# Display outputs: +n_servers=$(echo $SERVERS | wc --words) +echo "Total CPU Usage; Total Mem Usage; Physical(Logical) Cores; Total Mem; GPU Utilisation per GPU" +while :; do + done_count=0 + for euclid in $SERVERS; do + if [[ -s "$tmpdir/euclid-$euclid-cpu-mem" && -s "$tmpdir/euclid-$euclid-lscpu" && -s "$tmpdir/euclid-$euclid-gpu" ]]; then + cpu_usage=$(cat $tmpdir/euclid-$euclid-cpu-mem | grep -e '^%Cpu' | awk -F'[, ]+' '{print $2+$4+$6}') + mem_usage=$(cat $tmpdir/euclid-$euclid-cpu-mem | grep -e '^MiB Mem' | awk -F'[, ]+' '{print $8*100/$4}') + mem_size=$(cat $tmpdir/euclid-$euclid-cpu-mem | grep -e '^MiB Mem' | awk -F'[, ]+' '{print $4/1024}') + cores=$(cat $tmpdir/euclid-$euclid-lscpu | grep -e '^Core(s) per socket' -e 'Socket(s)' | paste -s | awk '{print $4*$6}') + threads=$(cat $tmpdir/euclid-$euclid-lscpu | grep '^CPU(s)' | awk '{print $2}') + gpu_file=$(cat $tmpdir/euclid-$euclid-gpu) + gpu_string=$(if [[ $gpu_file == "-1" || $gpu_file == *failed* ]]; then echo ""; else printf " %s%% GPU" "$(echo $gpu_file | tr ' ' ', ')"; fi) + printf "euclid-$euclid: %5.1f%% CPU %5.1f%% Mem %-3d(%-3d) Cores %4.0f GiB%s\n" $cpu_usage $mem_usage $cores $threads $mem_size "$gpu_string" + ((done_count++)) + else + printf "euclid-$euclid:\n" + fi + done + + # Break if all servers have responded + ((done_count == n_servers)) && break + + # Move cursor back to top + printf "\033[${n_servers}A" + + # Wait before re-checking + sleep 0.5 +done + +rm -r "$tmpdir"