Melhor maneira de tornar as variáveis locais em um script bash de código-fonte?

6

Eu tenho um script bash que gera um relatório sobre o progresso de alguns trabalhos de longa duração na máquina. Basicamente, este script pai percorre uma lista de scripts filhos (chamando-os todos com source ). Espera-se que os scripts filhos definam algumas variáveis específicas, que o script pai utilizará.

Hoje, descobri um bug em que uma variável definida pelo primeiro script filho acidentalmente era usada pelo segundo script filho, causando saída incorreta. Existe uma maneira limpa de evitar que esses tipos de bugs aconteçam?

Basicamente, quando eu source um script filho, existem algumas variáveis específicas que eu quero persistir de volta para o script pai. Meu script pai redefine essas variáveis específicas antes que source s cada novo script filho, portanto, não há problemas com elas. No entanto, alguns scripts filhos podem ter variáveis arbitrárias adicionais que ele usa localmente e que não devem persistir no script pai.

Obviamente, eu poderia manualmente desmarcar cada um deles no final do script filho, mas estes parecem propensos a erros se eu esquecer de um. Existe uma maneira mais adequada de obter um script e ter apenas algumas variáveis persistentes no script que chamou source ?

edit: Por motivos de clareza, aqui está uma espécie de versão simplificada do meu script pai:

echo "<html><body><h1>My jobs</h1>"

FILES=~/confs/*.sh
for f in $FILES; do
  # reset variables
  name="Unnamed job"
  secsSinceActive="Unknown"
  statusText="Unknown"

  # run the script that checks on the job
  source "$f"

  # print bit of report
  echo "<h3>$name</h3>"
  echo "<p>Last active: $secsSinceActive seconds ago</p>"
  echo "<p>Status: $statusText</p>"

echo "</body></html>"

E aqui está como um dos scripts filhos pode parecer:

name="My awesome job"

nowTime='expr $(date +%s) '
lastActiveTime='expr $(date +%s -r ~/blah.log)'
secsSinceActive='expr $nowTime - $lastActiveTime'

currentRaw=$(cat ~/blah.log | grep "Progress" | tail -n 1)
if [ -z "$currentRaw" ]; then
  statusText="Not running"
else
  statusText="In progress"
fi

As variáveis $ name, $ secsSinceActive e $ statusText precisam persistir de volta ao script pai, mas todas as outras variáveis devem desaparecer quando o script filho terminar.

    
por Hayden Schiff 30.07.2015 / 20:21

2 respostas

3

Envolva todo o script que você deseja inserir em uma função, adicione local antes das declarações que deseja usar na função e chame a função no final do script.

func () {
    local name="My awesome job"

    nowTime='expr $(date +%s) '
    lastActiveTime='expr $(date +%s -r ~/blah.log)'
    local secsSinceActive='expr $nowTime - $lastActiveTime'

    currentRaw=$(cat ~/blah.log | grep "Progress" | tail -n 1)
    if [ -z "$currentRaw" ]; then
      local statusText="Not running"
    else
      local statusText="In progress"
    fi
}
func
    
por 30.07.2015 / 22:14
-1

Eu acredito que a sintaxe para fazer uma variável local no bash é:

local variable_name=

Eu sei que isso funciona para funções e não sei como funciona com vários scripts.

    
por 30.07.2015 / 20:31