In der Bash-Dokumentation heißt es, dass bei jedem $RANDOM
Verweis eine Zufallszahl zwischen 0 und 32767 zurückgegeben wird. Wenn wir zwei aufeinanderfolgende Referenzen summieren, erhalten wir Werte von 0 bis 65534, was den gewünschten Bereich von 63001 Möglichkeiten für eine Zufallszahl zwischen 2000 und 65000 abdeckt.
Um es auf den genauen Bereich einzustellen, verwenden wir die Summe modulo 63001, die einen Wert von 0 bis 63000 ergibt. Dies erfordert wiederum nur ein Inkrement um 2000, um die gewünschte Zufallszahl zwischen 2000 und 65000 bereitzustellen. Dies kann sein wie folgt zusammengefasst:
port=$((((RANDOM + RANDOM) % 63001) + 2000))
Testen
# Generate random numbers and print the lowest and greatest found
test-random-max-min() {
max=2000
min=65000
for i in {1..10000}; do
port=$((((RANDOM + RANDOM) % 63001) + 2000))
echo -en "\r$port"
[[ "$port" -gt "$max" ]] && max="$port"
[[ "$port" -lt "$min" ]] && min="$port"
done
echo -e "\rMax: $max, min: $min"
}
# Sample output
# Max: 64990, min: 2002
# Max: 65000, min: 2004
# Max: 64970, min: 2000
Richtigkeit der Berechnung
Hier ist ein vollständiger Brute-Force-Test für die Richtigkeit der Berechnung. Dieses Programm versucht nur, alle 63001 verschiedenen Möglichkeiten zufällig unter Verwendung der zu testenden Berechnung zu generieren. Der --jobs
Parameter sollte die Ausführung beschleunigen, ist jedoch nicht deterministisch (die Gesamtzahl der generierten Möglichkeiten kann unter 63001 liegen).
test-all() {
start=$(date +%s)
find_start=$(date +%s)
total=0; ports=(); i=0
rm -f ports/ports.* ports.*
mkdir -p ports
while [[ "$total" -lt "$2" && "$all_found" != "yes" ]]; do
port=$((((RANDOM + RANDOM) % 63001) + 2000)); i=$((i+1))
if [[ -z "${ports[port]}" ]]; then
ports["$port"]="$port"
total=$((total + 1))
if [[ $((total % 1000)) == 0 ]]; then
echo -en "Elapsed time: $(($(date +%s) - find_start))s \t"
echo -e "Found: $port \t\t Total: $total\tIteration: $i"
find_start=$(date +%s)
fi
fi
done
all_found="yes"
echo "Job $1 finished after $i iterations in $(($(date +%s) - start))s."
out="ports.$1.txt"
[[ "$1" != "0" ]] && out="ports/$out"
echo "${ports[@]}" > "$out"
}
say-total() {
generated_ports=$(cat "$@" | tr ' ' '\n' | \sed -E s/'^([0-9]{4})$'/'0\1'/)
echo "Total generated: $(echo "$generated_ports" | sort | uniq | wc -l)."
}
total-single() { say-total "ports.0.txt"; }
total-jobs() { say-total "ports/"*; }
all_found="no"
[[ "$1" != "--jobs" ]] && test-all 0 63001 && total-single && exit
for i in {1..1000}; do test-all "$i" 40000 & sleep 1; done && wait && total-jobs
Um zu bestimmen, wie viele Iterationen erforderlich sind, um eine bestimmte Wahrscheinlichkeit p/q
zu erhalten, dass alle 63001-Möglichkeiten generiert wurden, können wir meines Erachtens den folgenden Ausdruck verwenden. Hier ist zum Beispiel die Berechnung für eine Wahrscheinlichkeit größer als 1/2 und hier für mehr als 9/10 .
shuf
ist relativ neu - ich habe es in den letzten Jahren auf Ubuntu-Systemen gesehen, aber nicht auf dem aktuellen RHEL / CentOS.