Estou puxando o meu cabelo tentando entender o script de shell e passando variáveis de ambiente, e quais não.
Estou tentando executar um script PHP do TextWrangler, que, por sua vez, abre um novo script PHP com o Terminal. (TextWrangler é um editor de texto que tem a opção de executar scripts, localizados em uma pasta designada, para operar no documento ativo atual, por exemplo).
O primeiro script está localizado em:
/Users/<username>/Library/Application Support/TextWrangler/Scripts/
... e seu conteúdo é:
#!/usr/bin/php
<?php
var_dump( $_SERVER );
chdir( __DIR__ );
$file = realpath( '../Unix Support/test.php' );
exec( sprintf( 'open -a Terminal "%s" &', $file ) );
exit( 0 );
?>
O segundo está em:
/Users/<username>/Library/Application Support/TextWrangler/Unix Support/
... e seu conteúdo é:
#!/usr/bin/php
<?php
var_dump( $_SERVER );
exit( 0 );
?>
O TextWrangler passa algumas variáveis de ambiente para o primeiro script (que eu posso acessar através de $_SERVER
), e elas são as esperadas. Por exemplo, o caminho correto para o documento atual que está ativo no TextWrangler.
Na primeira vez que executo o script, as variáveis de ambiente são automaticamente passadas corretamente para o segundo script (que abro com exec()
) também.
Agora vem a parte frustrante: quando eu troco o documento ativo no TextWrangler e executo o script novamente, o primeiro script recebe as variáveis de ambiente corretas do TextWrangler novamente, mas o segundo script ainda tem as variáveis de ambiente antigas, a menos que Eu matei o Terminal de antemão. Então, obviamente, a sessão do Terminal de alguma forma lembra as primeiras variáveis de ambiente e não quer atualizar.
Mas além de um entendimento muito básico, não tenho a menor idéia de como as variáveis de ambiente passam, de que escopo elas têm, etc. Então, alguém poderia explicar como eu posso fazer isso (se possível, começar com) que o segundo script recebe as variáveis de ambiente corretas novamente, sem ter que matar o Terminal toda vez?
Eu tentei definir explicitamente variáveis de ambiente no primeiro script antes de chamar exec()
, assim:
foreach( $_SERVER as $key => $value )
{
putenv( "$key=$value" );
}
exec( ... etc. );
Eu tentei não configurar as variáveis de ambiente no final, tanto no primeiro quanto no segundo script, assim:
foreach( $_SERVER as $key => $value )
{
putenv( "$key" );
}
Mas nada funciona como eu esperava. Qualquer novo insight totalmente apreciado.
edit:
Nesse meio tempo, encontrei uma solução alternativa, mas insatisfatória: quando eu chamo open -n -a Terminal ...
(observe o argumento -n
adicionado) com exec()
, ele inicia uma nova sessão do Terminal a cada vez, com o ambiente correto variáveis. Mas isso abre uma instância do Terminal completamente nova a cada vez.
update:
Eu simplifiquei o processo apenas usando um script em vez de dois agora, testando a variável de ambiente SHLVL
. Eu também consegui acabar com uma nova instância do Terminal agora, usando um arquivo temporário, como Scott sugeriu também. Isso resultou no seguinte. Mas ainda sinto que não é muito elegante.
$shellLevel = getenv( 'SHLVL' );
if( 1 == $shellLevel )
{
file_put_contents( 'env.dat', serialize( $_SERVER ) );
exec( sprintf( 'open -a Terminal "%s" &', __FILE__ ) );
exit( 0 );
}
else
{
$_SERVER = unserialize( file_get_contents( 'env.dat' ) );
unlink( 'env.dat' );
foreach( $_SERVER as $key => $value )
{
putenv( "$key=$value" );
}
}
Ainda estou abrindo outras sugestões (além do CLI e sugestões de arquivos que o Scott já propôs). A menos, é claro, simplesmente não é possível (Scott pareceu sugerir isso já).