como compartilhar variáveis de ambiente entre shells como globais relacionadas a um pid mestre?

7

Então, eu preciso compartilhar variáveis de ambiente entre shells e que as mudanças nas variáveis sejam prontamente reconhecidas por todos os shells, como variáveis globais. Mas eles devem estar relacionados a um PID mestre, para que eu possa ter dois scripts de shell em execução, cada um deles sendo um mestre com o mesmo nome de variável global, e os filhos apenas alterarão a variável relacionada ao seu PID mestre.

Eu uso bash para o script.

Minhas pesquisas atuais são estas:

Módulos
Eu li que eu poderia usar o projeto de módulos para isso: link , mas estou tendo um grande problema tentando fazê-lo, parece que falta exemplos? também "módulos" é uma palavra muito genérica, muito difícil de pesquisar porque se mistura com muitas outras coisas ... depois de algumas semanas minhas mãos ainda estão vazias ...

Arquivo de origem de texto simples
Eu li também eu deveria usar um arquivo de texto simples para armazenar / atualizar / ler variáveis, como um arquivo de script de origem, usando flock também para evitar a escrita simultânea. Mas existem problemas relacionados a fazer isso, como a simultânea mudança de variável simultaneamente por dois shells.

Alternativamente
Estou ciente de que depois que uma variável "global" é lida pelo shell, ela manterá esse valor até que outra leitura seja feita; e outra casca pode mudar isto na média enquanto também…
Pode ser um aplicativo externo muito rápido poderia fornecer esse armazenamento e não tentaríamos usar variáveis de ambiente como globais? mas meu palpite é que qualquer solução SQL será muito lenta ...

    
por Aquarius Power 19.08.2013 / 01:16

7 respostas

4

Você pode gravar o ambiente em um arquivo com export -p e lê-lo periodicamente nas outras instâncias com . (o comando include). Mas, como você observou, se houver modificações simultâneas, o resultado não será bonito.

Se você quiser que as modificações sejam propagadas instantaneamente, será necessário usar um wrapper em torno do export builtin que também propaga as alterações para os outros shells. No Linux, você pode usar o utilitário flock .

global_export () {
  {
    flock 0
    . /path/to/env
    [ $# -eq 0 ] || export "$@"
    export -p >/path/to/env
  } </path/to/env
}

Observe que você precisará chamar global_export sempre que atribuir um novo valor a uma variável exportada.

Isso é um pouco desajeitado. É provável que exista uma maneira melhor de resolver seu problema. A maneira mais óbvia é ter o comando que estiver usando essas variáveis de ambiente para ler os arquivos de configuração.

    
por 19.08.2013 / 01:31
2

Além de usar apenas flock da resposta de Giles, eu faria algo semelhante ao seguinte:

Registre um manipulador de sinal para recarregar o arquivo:

reload_env() {
 flock -s 3
 . /path/to/env
 flock -u 3
}
trap reload_env USR1

Uma função para gravar o arquivo e enviar um SIGUSR1 para todos os shells notificando-os para recarregar o arquivo:

export_env() {
 flock 3
 export -p >/path/to/env
 flock -u 3
 fuser -k -USR1 /path/to/env
}

Abra o arquivo, mas não faça nada com ele. Isso é apenas para que o fuser seja capaz de sinalizar esse shell:

exec 3>>/path/to/env

A ordem é um pouco importante. Pelo menos, a parte exec ... deve estar após a parte trap ... . Caso contrário, poderíamos abrir o arquivo e sermos sinalizados pela chamada fuser antes de registrarmos nosso manipulador de sinal.

NOTA: O código é completamente não testado, mas o princípio permanece.
NOTE2: Este código de exemplo é direcionado ao bash.

    
por 19.08.2013 / 04:03
2

Com o shell fish , use variáveis de escopo universal :

set -U var value

É claro que isso funciona somente em fish shells executados pelo mesmo usuário.

Se você quiser vinculá-lo a um master pid , inclua-o no nome da variável

set -U m${masterpid}var value
    
por 21.09.2013 / 09:11
1

Eu gostaria de apontar para pipes nomeados para essa finalidade. Aqui está um bom exemplo a considerar.

Os pipes nomeados são criados pelo comando:

mkfifo pipe_name

Você pode simplesmente escrever para ele por:

echo "This text goes to the pipe" > pipe_name

Por outro lado, você pode ler o pipe como:

read line < pipe_name;
echo $line

Você pode criar vários canais com base em quantos shells você deseja que eles se comuniquem. As coisas boas dos pipes são que elas não são apenas variáveis. Você pode realmente passar qualquer dados entre os processos. Você pode passar arquivos inteiros, linhas de textos, o que você quiser. Eu acredito que, com isso em mente, você pode simplificar muito seus scripts. Posso imaginar, se suas variáveis apontarem para um local de dados ou um arquivo, e o outro script tiver que lê-lo ou recuperá-lo, você pode passar diretamente os dados / arquivos sem precisar de uma variável.

    
por 21.09.2013 / 06:27
1

Se o ksh93 for uma opção, definitivamente há uma maneira de implementar o que você deseja com as funções de disciplina getter e setter que recuperariam / armazenariam o valor da variável de / para um armazenamento compartilhado.

Veja link para detalhes

Diferentemente do recurso% universal de variáveisfish, você tem acesso à implementação para restringir o compartilhamento de valor a um grupo de processos, vinculado a um pid mestre por meio de algum mecanismo no caso de uso, mantendo um único nome para a variável.

    
por 20.09.2013 / 21:30
0

Considerando seus comentários, você deseja o IPC básico entre os shell scripts. Gostaria apenas de escrever para arquivos (com uma renomeação para atomicidade)

varf=$(mktemp ./myvars.XXXXXX)
echo myvar=newval > $varf
mv -T -- $varf ./myvars

E ter leitores de origem. / myvars periodicamente.

O IPC é muito mais fácil com, por exemplo, o Python e o módulo de multiprocessamento.

    
por 20.09.2013 / 21:38
0

Existe também este projeto ScriptEchoColor :

Ele pode criar automaticamente e gerenciar para você um arquivo de texto do banco de dados. No primeiro script de execução, o arquivo BD será criado, os outros scripts serão vinculados a esse arquivo como seu próprio banco de dados para manipular valores de variáveis e, portanto, ambos podem trocar informações.

Um exemplo simples de compartilhamento com esses arquivos na pasta de exemplos : secExplShareEnvVarsA.sh, secExplShareEnvVarsB.sh

E um acesso de banco de dados compartilhado sincronizado (seguro e consistente de leitura / gravação) também: secExplSyncedShareEnvVarsA.sh, secExplSyncedShareEnvVarsB.sh

    
por 20.09.2013 / 07:36