#!/bin/bash # Thanks, ericwoud # https://ubuntuforums.org/showthread.php?t=2339439&page=2&p=13585921#post13585921 warn() { printf 'Error: %s\n' "$*" >&2; } with_rescan_remove() { local devname="$1" dev f hw_path rescan remove shift case "$devname" in */*) dev=/sys/class/$devname ;; *) for f in /sys/class/*/"$devname"; do dev=$f break done ;; esac [ "$dev" -a -d "$dev" ] || { warn "device not found: $devname"; return 1; } hw_path=$(dirname $(dirname $(realpath "$(dirname "$dev")/$(readlink "$dev")"))) rescan=$(dirname "$hw_path")/rescan remove="$hw_path"/remove if [ ! -e "$rescan" -a -e "$hw_path"/../pci_bus ]; then local p=$(dirname "$hw_path")/ rescan=$p/pci_bus/${p#*/pci}/rescan fi [ -e "$rescan" ] || { warn "sysfs special file not found: $rescan"; return 1; } [ -e "$remove" ] || { warn "sysfs special file not found: $remove"; return 1; } "$@" "$rescan" "$remove" } restart() { local rescan="$1" remove="$2" printf 1 > "$remove" || { warn "kernel remove failed"; return 2; } printf 1 > "$rescan" || { warn "kernel rescan failed"; return 3; } for ((i=0; i<100; ++i)); do [ -e "$remove" ] && break sleep 0.05 done } with_rescan_remove "$1" restart