Como recursivamente gerar scripts de shell?

3

Esta pergunta é, se for importante, preferencialmente no contexto do Bash, mas eu apreciaria uma solução em vários idiomas.

O problema que estou encontrando está no contexto de "terceirizar" um script com outro, mas fazendo isso de forma recursiva. O problema é que parece fazê-lo infinitamente.

O caso específico é o seguinte. Eu criei um script bash simples para carregar outros scripts bash no mesmo diretório. Como no meu projeto todos os scripts estão no mesmo diretório, isso por enquanto é ok.

Portanto, o "carregador de scripts" é o seguinte (um arquivo que define a seguinte função):

_source_script()
{
    # Define a few colors for the possible error messages below.
    RED=$(tput setaf 1)
    NORMAL=$(tput sgr0)

    EXPECTED_DIR="scripts"

    if [ "$#" -ge  "1" ]
    then
        EXPECTED_DIR=$1
    fi

    # Based on: http://stackoverflow.com/a/1371283/3924118
    CURRENT_DIR=${PWD##*/}

    if [ "$CURRENT_DIR" = "$EXPECTED_DIR" ]
    then
        for (( arg = 2; arg <= $#; arg++ ))
        do
            # Based on:
            # - https://sobrelinux.info/questions/27149/how-to-import-a-variable-from-another-script". ./${!arg}.sh\n"
            # Try to load script ${!arg}.sh
            . ./${!arg}.sh

            # If it was not loaded successfully, exit with status 1.
            if [ $? -ne 0 ]
            then
                printf "${RED}Script '${!arg}.sh' not loaded successfully. Exiting...${NORMAL}\n"
                exit 1
            fi
        done
    else
        printf "No script loaded: $CURRENT_DIR != $EXPECTED_DIR.\n"
        exit 1
    fi
} 

Para usar este "carregador de script", outros scripts devem primeiro "fonte" da seguinte forma:

. ./_source_script.sh

O problema é quando tento incluir outros scripts, fornecendo-os através da função _source_script . Por exemplo, quando tentei fazer (no script some_script.sh ):

_source_script scripts colors asserts clean_environment

continuou correndo para sempre.

Por dentro de colors Eu:

#!/usr/bin/env bash

# Colors used when printing.
export GREEN=$(tput setaf 2)
export RED=$(tput setaf 1)
export NORMAL=$(tput sgr0)
export YELLOW=$(tput setaf 3)

Por dentro de clean_environmnet Eu:

 ...

. ./_source_script.sh
_source_script scripts colors

e dentro de asserts.sh eu também tenho:

. ./_source_script.sh
_source_script scripts colors

Pelo que entendi, isso deve ser executado recursivamente até encontrar um script que não carregue nada ou encontre um ciclo, o que não é o caso.

Então, minha solução foi ter em some_script.sh o seguinte:

_source_script scripts colors 
_source_script scripts asserts
_source_script scripts clean_environment

ou seja, execute-os individualmente.

Então, por que não posso "fornecer" vários scripts em um loop?

    
por nbro 15.02.2017 / 15:48

1 resposta

0

Não olhando muito de perto o seu código, a abordagem geral incluiria algo parecido com os "protetores de cabeçalho" de C:

#ifndef HEADER_H
#define HEADER_H

/* The contents of the header file, with typedefs etc. */

#endif

em que HEADER_H é uma macro de pré-processador C específica para esse cabeçalho, usada somente para evitar a inclusão do cabeçalho novamente, caso já tenha sido incluída. Eu costumo criar uma macro com o nome derivado do próprio arquivo de cabeçalho, como MCMC_H para um arquivo de cabeçalho chamado mcmc.h .

Em um script de shell, isso pode ser tão fácil quanto

if [ -z "$script_source_guard" ]; then
script_source_guard=1

# ... do things (define functions etc.)

fi

O nome da variável script_source_guard precisa ser específico para este arquivo. Novamente, o nome pode ser arbitrariamente derivado do nome do arquivo de origem; um arquivo cujo nome é myfuncts.shlib pode ter uma variável de guarda chamada MYFUNCTS ou _MYFUNCTS ou guard_myfuncts ou qualquer outra coisa.

    
por 20.03.2017 / 15:44