У меня возникла эта проблема, и я решил ее, перейдя в Системные настройки
-> Рабочий стол
-> снимите / отметьте опцию Показывать значки рабочего стола
Странная возможность сворачивать рабочий стол! Надеюсь, это вам поможет.
Así es como normalmente hago mis opciones, pero creo que terminará alargando su secuencia de comandos... Sin embargo, toma opciones en cualquier orden.
while (( $# )); do
case $1 in
-n)
shift
number=$1
;;
-f)
shift
file_name=$1
;;
-p)
shift
password=$1
run=pass
;;
-s)
run=save
;;
-u)
shift
username=$1
;;
*)
thing=$1
save=what
;;
shift
esac
done
case $save in
save)
cat /dev/urandom \
| tr -dc A-Za-z0-9.-@ \
| head -c "$number" > "${DIR}/${file_name}.txt" && echo >> "${DIR}/${file_name}.txt"
cat "${DIR}/${file_name}.txt"
;;
pass)
cat /dev/urandom \
| tr -dc A-Za-z0-9.-@ \
| head -c "$number" ; echo
;;
*)
cat /dev/urandom \
| tr -dc A-Za-z0-9 \
| head -c "$thing" ; echo
;;
esac
El bucle while
se ejecutará mientras haya opciones. shift
pasa a la siguiente opción, por lo que recorrerá cada uno de los argumentos que pase y los ejecutará a través de la declaración del caso para manejarlos correctamente.
La siguiente secuencia de comandos es más larga que la suya, pero toda la longitud adicional se debe a que agregué una función usage
para imprimir un mensaje de ayuda de uso (que también sirve para imprimir un mensaje de error cuando se detecta una condición de error )y agregó muchos comentarios para explicar qué hace el código y por qué.
El código que analiza las opciones y hace el trabajo es mucho más corto y simple, y más fácil de expandir (p. actualmente toma una opción -u username
pero no hace nada con ella porque no mencionaste cómo debería usarse ). Se elimina todo el manejo especial de casos -, las "decisiones" sobre qué hacer y cómo hacerlo se toman en la declaración del caso y en algunas pruebas si/entonces inmediatamente posteriores.
También agregué una opción -d
para que pueda especificar un directorio de salida... pero eso es redundante como cualquier cosa excepto un ejemplo de cómo agregar otra opción, porque también agregué un código que verifica si el El archivo de salida contiene un carácter /
, y solo antepone$outdir
(renombrado desde su $DIR
-. Es un buen hábito usar nombres de variables en minúsculas en su script, reservando mayúsculas para utilidades estándar )si no es así. es decir, puede usar -f /path/to/file
o -d /path/to -f file
.
Por cierto, en lugar de crear un alias con la ruta completa a este script, recomiendo ponerlo en /usr/local/bin
o crear un directorio bin/
sub -en su directorio de inicio y agregar ~/bin
a su $ SENDERO. Luego, puede escribir y guardar tantos scripts personalizados como desee allí.
#!/bin/bash
usage() {
# this function prints a usage summary, optionally printing an error message
local ec=0
if [ $# -ge 2 ] ; then
# if printing an error message, the first arg is the exit code, and
# all remaining args are the message.
ec="$1" ; shift
printf "%s\n\n" "$*" >&2
fi
cat <<EOF
Usage:
$(basename $0) [-p | -s file | -u <user> | -d <dir> ] <[-l] length>
Generates a random password of specified length, containing only
alpha-numeric characters.
Required arguments:
-l <length> Length of password. Just the length without '-l' also works.
Options:
-p Allow some punctuation characters in password.
-s <file> Save output to filename.
-d <dir> Output directory for the save file
-u <user> Username. At present this does nothing.
-h This help message.
EOF
exit $ec
}
# Initialise variables
length=''
file=''
username=''
pattern='A-Za-z0-9'
outdir=$(dirname "$0")
# -s, -l, -u and -d require an arg. -h and -p don't. The leading ':' in
# the getopts string enables 'silent' error mode (i.e. we handle
# any errors ourselves)
while getopts ':hps:l:u:d:' opt; do
case "$opt" in
p) pattern='A-Za-z0-9.-@' ;;
s) file="$OPTARG" ;;
l) length="$OPTARG" ;;
u) username="$OPTARG" ;;
d) outdir="$OPTARG" ;;
h) usage ;;
:) usage 1 "-$OPTARG requires an argument" ;;
?) usage 1 "Unknown option '$opt'" ;;
esac
done
shift $((OPTIND -1))
# Length can be specified as either `-l nnn` or just `nnn` on the cmd line
# this code exits with an error message if no length is specified.
#
# It would probably be better to give length a default value instead.
# Just change `length=''` under the Initialise variables comment above
# to whatever you want as the default, and then delete the '[ -z "$1" ]'
# line below. Remember to update the usage message - documentation should
# always match what the code does.
if [ -z "$length" ] ; then
[ -z "$1" ] && usage 1 "Length option is required"
length="$1"
shift
fi
# if there are any remaining args on the line, we don't know what to do
# with them, so exit with an error message.
[ -n "$*" ] && usage 1 "Unknown arguments: '$*'"
password=$(cat /dev/urandom | tr -dc "$pattern" | head -c "$length")
# I don't know why you want an extra newline in the output, but do it anyway.
printf "$password\n\n"
if [ -n "$file" ] ; then
# if $file doesn't have a /, pre-pend "$outdir"
[[ $file =~ '/' ]] || file="$outdir/$file"
printf "$password\n\n" > "$file"
fi
Por cierto, ya existen numerosos programas generadores de contraseñas -. p.ej. pwgen y makepasswd
.
Solía usar pwgen
para generar contraseñas de más de 16 dígitos hasta que escribí mi propio generador de frases de contraseña que selecciona aleatoriamente una cantidad de palabras de /usr/share/dict/words
y las une con -generado aleatoriamente 1 -3 dígitos números y/o puntuación. /usr/share/dict/words
es todo -en minúsculas, por lo que mi secuencia de comandos pone aleatoriamente en mayúscula algunas de las letras. Esto genera contraseñas muy largas pero fáciles de recordar. Los dígitos aleatorios, la puntuación y las mayúsculas aumentan el espacio de búsqueda para el descifrado de fuerza bruta -y ayudan a garantizar que la seguridad de la contraseña no se vea comprometida por la previsibilidad del diccionario de palabras.
por ej.
$ random-password.sh
31 surVeying % deRAngement 6 ratiocinations 51 sunDowns
$ printf '%s' '31 surVeying % deRAngement 6 ratiocinations 51 sunDowns' | wc -c
55
La longitud de la contraseña es mucho más importante que la complejidad -cualquier contraseña de menos de 10 caracteres se puede descifrar en muy poco tiempo con -hardware moderno (un segundo o menos durante <= 7 caracteres, horas para 8 caracteres, unos meses para 10 caracteres ). Una contraseña de 55 caracteres es efectivamente indescifrable dentro de la vida útil del universo con la tecnología actual (, por lo que debería ser segura durante al menos 10 años ).
El problema es que cuanto más larga es una contraseña, más simple debe ser para que un humano pueda recordarla. Descubrí que solo necesito recordar el inicio de la contraseña y, al escribirla varias veces, asocio automáticamente (y, por lo tanto, recuerdo )los siguientes dígitos y palabras en la frase sin sentido.
Это вариант вашего скрипта:
#!/bin/bash
opt_l=8 # password length is 8 by default
opt_o=/dev/stdout # write to standard output by default
opt_s=0 # insecure password by default
opt_u= # no default username
while getopts 'l:o:su:' opt; do
case "$opt" in
l) opt_l=$OPTARG ;;
o) opt_o=$OPTARG ;;
s) opt_s=1 ;;
u) opt_u=$OPTARG ;;
*) echo 'Error parsing options' >&2
exit 1
esac
done
args=( "$opt_l" 1 )
if (( opt_s )); then
args=( -s "${args[@]}" )
fi
if [ -n "$opt_u" ]; then
printf '%s: %s\n' "$opt_u" "$( pwgen "${args[@]}" )" >"$opt_o"
else
pwgen "${args[@]}" >"$opt_o"
fi
Я изменил названия некоторых флагов, чтобы они больше соответствовали тому, что используют стандартные инструменты. Вместо того, чтобы печатать сообщение об ошибке при обнаружении неподдерживаемого флага, вы можете вывести пользователю некоторую информацию об использовании.
Главное здесь использование getopts
. Он принимает спецификацию в виде строки параметров, которые вы используете. :
в строке означает, что предыдущий символ опции принимает аргумент (другие опции являются логическими ).
В цикле while
$opt
будет опцией, а $OPTARG
будет аргументом опции, если флаг принимает аргумент.
Обычно также выполняется shift "$(( OPTIND - 1 ))"
после цикла, но поскольку этот скрипт не принимает дополнительные операнды в командной строке, кроме опций и их аргументов, в этом нет необходимости. shift
гарантирует, что дополнительные операнды будут доступны как $1
, $2
и т. д.
Вы можете использовать скрипт как
$./script.sh -l 4 # generates password of length 4 in the terminal
$./script.sh -l 4 -o file # generates password of length 4 and saves to "file"
$./script.sh -u bob # generates password of length 8, prepends with username "bob"
$./script.sh -s -u bob # generates more random password of length 8, prepends with username "bob"
-s -u bob
совпадает с -ubob -s
и -subob
, а поскольку-u alice -s -u bob
(более поздние параметры переопределяют более ранние ).
Было бы довольно легко удалить pwgen
из этого и просто использовать другой генератор паролей. Чтобы упростить это, можно поместить генератор паролей в отдельную функцию, что означает, что основной скрипт никогда не будет изменяться при замене генератора :
#!/bin/bash
passgen () {
local args=( "$opt_l" 1 )
if (( opt_s )); then
args=( -s "${args[@]}" )
fi
pwgen "${args[@]}"
}
opt_l=8 # password length is 8 by default
opt_o=/dev/stdout # write to standard output by default
opt_s=0 # insecure password by default
opt_u= # no default username
while getopts 'l:o:su:' opt; do
case "$opt" in
l) opt_l=$OPTARG ;;
o) opt_o=$OPTARG ;;
s) opt_s=1 ;;
u) opt_u=$OPTARG ;;
*) echo 'Error parsing options' >&2
exit 1
esac
done
if [ -n "$opt_u" ]; then
printf '%s: %s\n' "$opt_u" "$( passgen )" >"$opt_o"
else
passgen >"$opt_o"
fi
Например, это примерно ваш генератор:
passgen () {
local source=/dev/urandom
local chars='A-Za-z0-9'
if (( opt_s )); then
chars="$chars"'.-@'
fi
tr -dc "$chars" <"$source" | head -c "$opt_l"
}
... и следующее генерирует фразу-пароль, используя слова из/usr/share/dict/words
(количество слов берется из опции -l
). Если используется опция -s
,он добавляет случайное число в конец вместо последнего слова.
passgen () {
local dict=/usr/share/dict/words
local numwords=$opt_l
if (( opt_s )); then
numwords=$(( numwords - 1 ))
fi
{
shuf -n "$numwords" "$dict"
if (( opt_s )); then
printf '%d\n' "$RANDOM"
fi
} | tr '\n' ' ' | sed 's/ $//'
}
Работа с этой последней функцией passgen
, команда
./script.sh -s -u bob -l 3
может генерировать что-то вроде
bob: cassis befluster 22625