Fluxo de Controle Iterativo no Script Subshelled [closed]

1

Eu tenho um script de shell (A) que está sendo chamado por outro script (B). Neste script (A) estou criando alguns diretórios e movendo alguns arquivos como trabalho preparatório para o resto do script funcionar bem. Script (A) é chamado pelo script (B) de uma maneira iterativa, eu só quero a criação de diretórios e movimentação de arquivos para ocorrer apenas uma vez, ou seja, durante o primeiro loop.

O que posso fazer para executar uma parte do meu script apenas uma vez?

    
por Syed Moez 26.12.2014 / 01:58

3 respostas

1

Você precisa de uma qualidade relativamente única do ambiente em que confiar. Isso não é fácil de encontrar - especialmente se você está chamando um script separado iterativamente em um loop e espera que ele se comporte de maneira diferente para cada ocorrência (por que não partes do mesmo script nesse caso?) .

De qualquer forma, o mais comum é usar um arquivo de travamento - ou algo parecido - para esse tipo de coisa. Para fazer isso, você precisa desse ambiente único. Considere o seguinte:

sh -c 'echo "$PPID" "$$"
       for i in 1 2 3 4 5
       do sh -c "echo \"\$PPID\""
       done'

OUTPUT

25711 28929
28929
28929
28929
28929
28929

Se você puder confiar no chamador que fornece seu pid para você na variável de ambiente $PPID , pode ser exatamente o que você precisa. Por exemplo:

#!/bin/sh
#script a
LOCKDIR=${TMPDIR:-/tmp}/${0##*/}.$PPID

init() { mkdir "$LOCKDIR" || exit
#        do other initialization tasks
}

loop() { : do the iterable tasks here; }

[ -d "$LOCKDIR" ] || init
loop

... e ...

#!/bin/sh
#script b
a='/path/to/script/a'
for stuff in $things
do "$a" "$stuff"
done
rm -rf "${TMPDIR:-/tmp}/${a##*/}.$$"

Sério, no entanto, eu não encontrei muitas situações em que fazer esse tipo de coisa é uma boa idéia - se eu estou chamando outro shell-script iterativamente e eu devo confiar em seu ambiente então eu provavelmente . fonte o conteúdo do script no shell atual e executá-lo dessa maneira. Eu faria isso, ou seja, se eu tivesse muito certeza de que o script que eu estava executando estava escrito com segurança.

    
por 26.12.2014 / 03:08
2

Existem várias maneiras de passar essas informações do script de chamada para o script chamado. Uma é usar um parâmetro ( ./script --init vs. ./script ) ou um valor de parâmetro ( ./script --init=0 vs. ./script --init=1 ). Eu acho que o método mais simples é usar uma variável de ambiente:

script B:

init=0
while whatever; do INIT=$((init++)) ./script_A; done

script A:

[...]
if [ 0 -eq "$INIT" ]; then
  : make preparations
fi
[...]

Se o script A puder ser executado sem ser chamado pelo script B, a variável que está faltando deverá ser manipulada (antes da instrução if , é claro):

: ${INIT:=1}
    
por 26.12.2014 / 02:17
0

Eu criei um arquivo de texto de gatilho, estou usando o número de contagem de linhas como o gatilho para minha instrução if e, em seguida, dentro da instrução if estou editando o arquivo de texto para adicionar mais linhas a ele. Dessa forma, a instrução if será acionada apenas uma vez por meio de quaisquer iterações. Isso é resolvido por um código muito simples. toque em Trigger.txt n = $ (wc -l > Trigger.txt fi

    
por 26.12.2014 / 19:22

Tags