analisando uma opção de comando em um script bash

0

Eu escrevi um script "rápido" e depois pensei em adicionar uma opção "- nano" que desligaria meu comutador de e-mail (do qual a sintaxe é inserida do eco).

Eu achei que seria fácil, mas eu acho que, fundamentalmente, eu não estruturei bem o roteiro original, então essa "opção" está me matando.

Muito novo para bater… AGRADECIMENTOS!

MEU MARAVILHOSO SCRIPT DE TRABALHO!

 ## Current threshold value setting
 THRESHOLD="80"                                      

 ## Input Files and Mailx
 LOCATIONS="fsIn.txt"                                               ## Edit "fsIn.txt" to add or change filesystems
 TOLIST="$(cat toList.txt | tr -s '\n' ' ' )"                       ## Sets who receives email if an error condition exists
 REPLYTO="$(cat replyTo.txt | tr -s '\n' ' ' )"                     ## sets the reply to email addresses
 FROM=”SCRIPT TEAM"                             ## Sets the "from" address on error emails
 SUBJECT="$HOST: ! STORAGE LEVEL MET OR EXCEEDED !"         ## Sets the subject line
 ############

 for i in $(cat $LOCATIONS)

 do

 ## Main df pipeline to return usage percentage
 CAP=$(df -PH --no-sync "$i" | awk 'NR>1'| awk {'print $5'} | sed 's/.$//')

for i in $(cat $LOCATIONS)                  #Several different file system locations are ‘catted’ in here .  E.g.  /dev

do

## Main df pipeline to return usage percentage to stdout and piped to mailx
CAP=$(df -PH --no-sync "$i" | awk 'NR>1'| awk {'print $5'} | sed 's/.$//')
        if [ $CAP -ge $THRESHOLD ]
            then
           (echo                               
            echo "---------- CAPACITY TEST FAILED ---------- "
            echo -n "  SYSTEM NAME: " ; uname -n
            echo -n "  USER DETAIL: " ; whoami
            echo "  TEST AREA:   $i "
            echo "  USED SPACE:  $CAP% "
            echo "  THRESHOLD:   $THRESHOLD% "
            echo "  !!!!!! THRESHOLD EXCEEDED !!!!!! ") | tee >(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
            echo

        else
            echo
            echo "++++++++++ CAPACITY TEST PASSED ++++++++++ "
            echo "  TEST AREA:   $i "
            echo "  USED SPACE:  $CAP% "
            echo "  THRESHOLD:   $THRESHOLD% "
            echo " !!! SUCCESS SUCCESS SUCCESS SUCCESS !!! "
            echo
    fi

done

exit 0

Isso funciona perfeitamente! Mas eu não tenho ideia de como reestruturar isso para incluir uma opção –nomail. Parece que "caso" pode ser prudente, mas estou perdido aqui.

Alguma opinião?

Muito obrigado!

    
por SSDdude 06.03.2018 / 22:47

3 respostas

0

Atualizar

Voltei e li toda a sua pergunta e percebi que tinha originalmente respondido a uma pergunta um pouco diferente da que você perguntou, então aqui vai:

  1. Sua estrutura está bem. Analise a opção de comando no início do script.

  2. Sim, você pode usar uma declaração case , verificando com $1 (veja minha resposta original abaixo), embora se você estiver planejando apenas uma única opção, você pode executar um único teste com a mesma facilidade veja minha resposta original abaixo). Para usar uma instrução case com várias opções possíveis, coloque-a em um loop while , no formato while "$1" ; do case ... esac; shift; done . O comando shift substituirá $1 pela próxima palavra / opção da sua linha de comando.

Resposta original

Existem várias maneiras de lidar com isso. Se esta é a única opção, ou se houver apenas alguns, você pode considerar analisá-lo manualmente. No shell-speak, todas as palavras após o comando shell são chamadas parâmetros , e cada uma é atribuída a um parâmetro posicional , no formato $n with n começando em 1. Assim, você pode realizar um teste para verificar se [[ $1 == "--nomail" ]] e agir de acordo. Essa é a maneira simples e direta para apenas uma única opção.

Para scripts de shell mais complexos com muitas opções, você pode querer usar algum tipo de comando getopts para analisar as opções para você. O shell bash inclui uma versão de getopts como um arquivo interno, e você pode aprender mais sobre isso digitando man bash na linha de comando e, em seguida (se o pager padrão estiver definido como less ) /^ *getopt .

    
por 06.03.2018 / 23:00
0

Outras respostas já mencionaram como obter uma opção de linha de comando (por exemplo, verificando "$1" diretamente ou usando getopts ). Minha resposta é sobre como modificar rapidamente seu script para usar uma opção --nomail sem ter que reescrever seu script do zero. No longo prazo, você provavelmente deve fazer isso, apenas para aproveitar as melhorias graduais na sua habilidade e conhecimento de script de shell.

A maneira óbvia é usar um arquivo variável ou temporário para armazenar a saída que você deseja imprimir ou imprimir & e, em seguida, escolha o que fazer com ela em cada ocasião.

A maneira menos óbvia é substituir o pipe para tee >(mailx ...) por um pipe para uma chamada de função que toma a decisão de tee seu stdin para mailx ou apenas cat it. Com este método, não há necessidade de armazenar a saída, apenas canalizá-la e deixar a função lidar com ela - o resto do seu código não precisa saber ou se importar (e, mais importante, não precisa ser escrito para lidar com ambos os casos).

Veja como ...

Primeiro, adicione um código como este em algum lugar perto do início do seu script:

# set the default, i.e. to send mail.
send_email=1

# Very basic option processing. Using getopts would be better.
[ "$1" == "--nomail" ] && send_email=''

myoutput() {
  if [ "$send_email" ] ; then
    # print stdin to stdout AND mail it
    tee <(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
  else 
    # only print stdin to stdout. no mail.
    cat
  fi
}

Em segundo lugar, use a função definida aqui substituindo o | tee ... no seu for loop por | myoutput .

( myoutput é um nome inválido para uma função. Renomeie para cat_or_mail ou o que for mais útil para você)

Idealmente, a função deve ter argumentos em vez de depender de variáveis globais e deve ser escrita assim:

myoutput() {
  local send_email SUBJECT FROM REPYLTO TOLIST

  # more of the primitive option handling.  getopts can and should be used
  # inside a function too.    
  send_email="$1"
  SUBJECT="$2"
  FROM="$3"
  REPLYTO="$4"
  TOLIST="$5"

  # add code here to check if those variables contain valid values.
  # print warnings and/or abort and/or set appropriate defaults if they don't.

  if [ "$send_email" ] ; then
    # print stdin to stdout AND mail it
    tee <(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
  else 
    # only print stdin to stdout. no mail.
    cat
  fi
}

e chamá-lo como ... | myoutput "$send_email" "$SUBJECT" "$FROM" "$REPLYTO" "$TOLIST"

Isso torna a função reutilizável sem ter que configurar variáveis globais de antemão - apenas chame-a com os valores que você precisa.

    
por 07.03.2018 / 04:55
0

Uma resposta fácil é dupla:

  • Defina um sinalizador como send_email to true e desmarque-o ou defina-o como false se seu argumento de supressão de e-mail estiver presente.
  • Componha seu e-mail antecipadamente montando um arquivo variável ou temporário que seria a saída e, em seguida, punindo o envio real de e-mail para uma chamada de função:

Por exemplo:

send_email="true"
handle_email() {
    echo "$email_body" | mailx -s "$subject" -r "$from" -S replyto="$replyto" ${recipients[@]}
}

[...]
if [[ "--nomail" == "$1" ]]; then
    send_email=false
fi
[...]
if [[ true == "$send_email ]]; then
    handle_email
fi
    
por 06.03.2018 / 22:59