I'm pulling my hair out trying to understand shell scripting and passing environment variables, and what not.
I'm trying to execute a PHP script from TextWrangler, that in it's turn opens a new PHP script with Terminal. (TextWrangler is a text editor that has the option to execute scripts, located in a designated folder, to operate on the current active document, for instance).
The first script is located in:
/Users/<username>/Library/Application Support/TextWrangler/Scripts/
... and its contents are:
#!/usr/bin/php
<?php
var_dump( $_SERVER );
chdir( __DIR__ );
$file = realpath( '../Unix Support/test.php' );
exec( sprintf( 'open -a Terminal "%s" &', $file ) );
exit( 0 );
?>
The second is in:
/Users/<username>/Library/Application Support/TextWrangler/Unix Support/
... and its contents are:
#!/usr/bin/php
<?php
var_dump( $_SERVER );
exit( 0 );
?>
TextWrangler passes some environment variables to the first script (which I can access through $_SERVER
), and they are as expected. For instance the correct filepath to the current document that is active in TextWrangler.
The first time I execute the script, the environment variables are automatically passed correctly to the second script (that I open with the exec()
) as well.
Now comes the frustrating part: when I switch the active document in TextWrangler and run the script again, the first script receives the correct environment variables from TextWrangler again, but the second script still has the old environment variables, unless I had killed Terminal beforehand. So obviously the Terminal session somehow remembers the first environment variables, and doesn't want to update.
But apart from a this very basic understanding, I don't have the faintest idea how environment variables passing work, what scope they have, etc. So, could somebody explain how I can make it so (if possible, to begin with) that the second script receives the correct environment variables again, as well, without having to kill Terminal each time?
I've tried explicitly setting environment variables in the first script before calling exec()
, like so:
foreach( $_SERVER as $key => $value )
{
putenv( "$key=$value" );
}
exec( ... etc. );
I've tried unsetting the environment variables at the end, in both the first and second scripts, like so:
foreach( $_SERVER as $key => $value )
{
putenv( "$key" );
}
But nothing works as I expect. Any new insights thoroughly appreciated.
edit:
In the meantime I've found an alternative, but unsatisfactory solution: when I call open -n -a Terminal ...
(note the added -n
argument) with exec()
, it starts a new Terminal session each time, with the correct environment variables. But this opens a completely new Terminal instance each time.
update:
I've simplified the process a bit by only using one script in stead of two now, through testing the environment variable SHLVL
. I've also managed to do away with a new Terminal instance now, by using a temporary file, like Scott suggested as well. This resulted in the following. But I still feel it's not very elegant.
$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" );
}
}
So, I'm still open too other suggestions (besides the CLI and file suggestions that Scott already proposed). Unless, of course, it is simply not possible (Scott seemed to hint at this already).