O script a seguir é mais longo que o seu, mas todo o comprimento extra é porque adicionei uma função usage
para imprimir uma mensagem de ajuda de uso (ela também serve para imprimir uma mensagem de erro quando uma condição de erro é detectada) e adicionada muitos comentários para explicar o que o código faz e por quê.
O código que analisa as opções e faz o trabalho é muito mais curto e mais simples, e mais fácil de expandir (por exemplo, atualmente leva uma opção -u username
, mas não faz nada com isso porque você não mencionou como deve ser usado). Todo o manuseio de casos especiais é eliminado, as "decisões" sobre o que fazer e como fazer são feitas na declaração de caso e em alguns testes if / then imediatamente depois.
Eu também adicionei uma opção -d
para que você possa especificar um diretório de saída ... mas isso é redundante como qualquer coisa, exceto um exemplo de como adicionar outra opção, porque eu também adicionei código que verifica se O arquivo de saída contém um caractere /
e apenas prefixa $outdir
(renomeado de $DIR
- é um bom hábito usar nomes de variáveis minúsculas no seu script, reservando maiúsculas para utilitários padrão) caso não seja. ou seja, você pode usar -f /path/to/file
ou -d /path/to -f file
.
BTW, em vez de criar um alias com o caminho completo para esse script, recomendo apenas colocá-lo em /usr/local/bin
ou criar um subdiretório bin/
no diretório home e adicionar ~/bin
ao seu $ PATH. Então você pode simplesmente escrever e salvar quantos scripts personalizados desejar.
#!/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
BTW, vários programas de geração de senha já existem. por exemplo. pwgen e makepasswd
.
Eu usei pwgen
para gerar senhas de 16 + dígitos até que eu escrevesse meu próprio passphrase generator que selecionasse aleatoriamente um número de palavras de /usr/share/dict/words
e as unisse com números de 1-3 dígitos gerados aleatoriamente e / ou pontuação. /usr/share/dict/words
é todo em minúsculas, então meu script capitaliza aleatoriamente algumas das letras. Isso gera senhas muito longas, mas fáceis de lembrar. Os dígitos aleatórios, pontuação e uso de letras maiúsculas aumentam o espaço de pesquisa para o cracking de força bruta e ajudam a garantir que a força da senha não seja comprometida pela previsibilidade do dicionário de palavras.
por exemplo,
$ random-password.sh
31 surVeying % deRAngement 6 ratiocinations 51 sunDowns
$ printf '%s' '31 surVeying % deRAngement 6 ratiocinations 51 sunDowns' | wc -c
55
O tamanho da senha é muito mais importante que a complexidade - qualquer senha com menos de 10 caracteres pode ser quebrada em pouco tempo com hardware moderno (um segundo ou menos para < = 7 caracteres, horas para 8 caracteres, alguns meses para 10 caracteres). Uma senha de 55 caracteres é efetivamente ininterrupta durante a vida útil do universo pela tecnologia atual (portanto, deve ser segura por pelo menos 10 anos).
O problema é que quanto mais longa for a senha, mais simples será para um ser humano conseguir se lembrar dela. Acho que só preciso lembrar o início da senha e, digitando-a algumas vezes, associo automaticamente (e, portanto, lembro) os próximos dígitos e palavras na frase sem sentido.