#!/bin/sh set -eu SECONDS=300 DEVICES="" EXCLUDE="" FORMAT="" JOHN_DIR="/usr/local/lib/bee/john/run" JOHN_BIN="${JOHN_DIR}/john" usage() { echo "usage: $0 [--seconds N] [--devices 0,1] [--exclude 2,3] [--format name]" >&2 exit 2 } normalize_list() { echo "${1:-}" | tr ',' '\n' | sed 's/[[:space:]]//g' | awk 'NF' | sort -n | uniq | paste -sd, - } contains_csv() { needle="$1" haystack="${2:-}" echo ",${haystack}," | grep -q ",${needle}," } while [ "$#" -gt 0 ]; do case "$1" in --seconds|-t) [ "$#" -ge 2 ] || usage; SECONDS="$2"; shift 2 ;; --devices) [ "$#" -ge 2 ] || usage; DEVICES="$2"; shift 2 ;; --exclude) [ "$#" -ge 2 ] || usage; EXCLUDE="$2"; shift 2 ;; --format) [ "$#" -ge 2 ] || usage; FORMAT="$2"; shift 2 ;; *) usage ;; esac done [ -x "${JOHN_BIN}" ] || { echo "john binary not found: ${JOHN_BIN}" >&2; exit 1; } ALL_DEVICES=$(nvidia-smi --query-gpu=index --format=csv,noheader,nounits 2>/dev/null | sed 's/[[:space:]]//g' | awk 'NF' | paste -sd, -) [ -n "${ALL_DEVICES}" ] || { echo "nvidia-smi found no NVIDIA GPUs" >&2; exit 1; } DEVICES=$(normalize_list "${DEVICES}") EXCLUDE=$(normalize_list "${EXCLUDE}") SELECTED="${DEVICES}" if [ -z "${SELECTED}" ]; then SELECTED="${ALL_DEVICES}" fi FINAL="" for id in $(echo "${SELECTED}" | tr ',' ' '); do [ -n "${id}" ] || continue if contains_csv "${id}" "${EXCLUDE}"; then continue fi if [ -z "${FINAL}" ]; then FINAL="${id}" else FINAL="${FINAL},${id}" fi done [ -n "${FINAL}" ] || { echo "no NVIDIA GPUs selected after filters" >&2; exit 1; } JOHN_DEVICES="" for id in $(echo "${FINAL}" | tr ',' ' '); do opencl_id=$((id + 1)) if [ -z "${JOHN_DEVICES}" ]; then JOHN_DEVICES="${opencl_id}" else JOHN_DEVICES="${JOHN_DEVICES},${opencl_id}" fi done echo "loader=john" echo "selected_gpus=${FINAL}" echo "john_devices=${JOHN_DEVICES}" cd "${JOHN_DIR}" choose_format() { if [ -n "${FORMAT}" ]; then echo "${FORMAT}" return 0 fi for candidate in sha512crypt-opencl pbkdf2-hmac-sha512-opencl 7z-opencl sha256crypt-opencl md5crypt-opencl; do if ./john --test=1 --format="${candidate}" --devices="${JOHN_DEVICES}" >/dev/null 2>&1; then echo "${candidate}" return 0 fi done return 1 } CHOSEN_FORMAT=$(choose_format) || { echo "no suitable john OpenCL format found" >&2 ./john --list=opencl-devices >&2 || true exit 1 } echo "format=${CHOSEN_FORMAT}" exec ./john --test="${SECONDS}" --format="${CHOSEN_FORMAT}" --devices="${JOHN_DEVICES}"