Passar argumentos para uso em um processo neto

5

Eu tenho uma lista de argumentos e três processos:

bash_script -> child -> grandchild

A lista de argumentos é destinada ao neto. Eu posso modificar todos os três processos. O roteiro do avô recebe um argumento por si mesmo.

O seguinte é uma maneira apropriada de passar os argumentos restantes para o neto?

#!/usr/bin/env bash
# This is the grandfather    
first_arg="$1"
shift 1;

export MY_ARGS="$@"

Eu "espalhei" a variável env mais tarde, no processo filho, como parte do comando que chama o neto, algo como:

grandchild --foo "$MY_ARGS"  # append $MY_ARGS as arguments to foo
    
por Alexander Mills 19.06.2018 / 20:11

4 respostas

5

Em um script, você não deve rebaixar um array para uma string. Uma variável de ambiente e seu valor é um par key=value simples, em que key e value são strings. Desmembrar os parâmetros posicionais para uma string simples (por concatenação) tornará difícil manter a separação entre eles, e seria difícil obter a citação correta quando você acabar querendo usá-los.

Em vez disso, passe os parâmetros posicionais (argumento de linha de comando) que você deseja passar para o próximo script em sua linha de comando.

#!/bin/bash

first_arg=$1
shift

# later ...

./my_other_script "$@"

No outro script:

#!/bin/bash

# use "$@" here
foo --bar "$@"
    
por 19.06.2018 / 20:29
2

EDIT: parece que você não pode exportar matrizes no bash. Pode ser necessário exportar uma função que configura a matriz ou algo semelhante.

Você deve usar uma matriz, caso contrário, os argumentos com espaços serão expandidos para várias palavras.

export MY_ARGS=("$@")


foo --bar "${MY_ARGS[@]}"
    
por 19.06.2018 / 20:31
2

Não sei por que as pessoas estão confusas com a pergunta, mas talvez a pergunta seja confusa, eis o que parece funcionar bem para mim:

my_args_array=("$@")
export MY_ARGS="${my_args_array[@]}"

então simplesmente usamos MY_ARGS da seguinte forma:

foo --bar $MY_ARGS

note como @Kusalananda aponta: isso irá falhar se os argumentos originais tiverem espaços em branco neles. E, nesse caso, é melhor passar argumentos por meio de processos filhos usando $@ , em vez de uma variável env.

    
por 19.06.2018 / 20:49
2

A resposta geral é essa. Você pode passar os argumentos usando:

  • parâmetros posicionais da linha de comando
  • variáveis de ambiente
  • qualquer IPC (comunicação entre processos) disponível no seu sistema operacional

Para focar apenas os dois primeiros,

  • Os parâmetros posicionais são o caminho mais natural. Isso envolve a possível edição e posterior transmissão de "$@" , que representa todos os parâmetros posicionais atualmente definidos. Isso deve ser feito em todos os estágios da hierarquia de processos.
  • As variáveis de ambiente não são tão diretas quanto os parâmetros posicionais, pois vêm em uma forma de par de chave e valor. Mesmo se você passar valores dessa maneira, você precisa das chaves para obtê-los. Contanto que eles não sejam as únicas variáveis de ambiente, que eu não assumiria sem uma consideração adequada. Mas esse método é viável. Tudo o que você precisa fazer é compartilhar as chaves entre as partes interessadas. As próprias chaves podem ser baseadas em um padrão. Veja um exemplo de como isso pode ser feito.

    Existem dois scripts - p.bash e c.bash . p significa pai / mãe, enquanto c é filho. Eles podem ser separados por intermediários, desde que não removam os valores transmitidos pelo ambiente. Para simplificar, esses dois scripts têm uma conexão imediata nesse p.bash calls c.bash .

    Aqui está o p.bash :

    #!/bin/bash
    shift #consume the first argument
    #parse and export the other arguments
    prefix=abcdef_
    i=0
    for a in "$@"; do
        export "$prefix""$i"="$a"
        ((i++))
    done
    ./c.bash
    

    E aqui está o c.bash :

    #!/bin/bash
    #consume the env arguments
    prefix=abcdef_
    env | grep ^"$prefix"
    

    E aqui está a execução:

    $ ./p.bash arg "1 2" "3 4" "5 6"
    abcdef_0=1 2
    abcdef_1=3 4
    abcdef_2=5 6
    

    Vou explicar duas linhas, uma de cada script.

    O primeiro é o gerador,

     export "$prefix""$i"="$a"
    

    export preenche o ambiente com variáveis do formulário abcdef_0 , abcdef_1 , etc. Agora, os processos filhos podem encontrá-los em seus ambientes. (Desde que não sejam desfeitos por algum intermediário.)

    env | grep ^"$prefix" na criança é o consumidor. env lista as variáveis de ambiente e grep filtra todas as linhas não associadas ao prefixo responsável pela transmissão em questão. Depois de entender o que está acontecendo aqui, você poderá acessar as variáveis transmitidas e utilizá-las dentro do processo descendente.

por 19.06.2018 / 22:53