Я витягаю волосся, намагаючись зрозуміти сценарій оболонки та прохідні змінні середовища, а що ні.
Я намагаюся виконати скрипт PHP від TextWrangler, що, в свою чергу, відкриває новий скрипт PHP з терміналом. (TextWrangler - це текстовий редактор, який має можливість виконувати скрипти, розташовані у визначеній папці, наприклад, для роботи над поточним активним документом).
Перший сценарій розташований у:
/Users/<username>/Library/Application Support/TextWrangler/Scripts/
... і його вміст:
#!/usr/bin/php
<?php
var_dump( $_SERVER );
chdir( __DIR__ );
$file = realpath( '../Unix Support/test.php' );
exec( sprintf( 'open -a Terminal "%s" &', $file ) );
exit( 0 );
?>
Друга - у:
/Users/<username>/Library/Application Support/TextWrangler/Unix Support/
... і його вміст:
#!/usr/bin/php
<?php
var_dump( $_SERVER );
exit( 0 );
?>
TextWrangler передає деякі змінні середовища до першого сценарію (до якого я можу отримати доступ $_SERVER
), і вони є такими, як очікувалося. Наприклад, правильний файловий шлях до поточного документа, активного в TextWrangler.
Перший раз, коли я виконую скрипт, змінні середовища автоматично передаються правильно і другому сценарію (який я відкриваю разом із exec()
).
Тепер настає розчарування: коли я перемикаю активний документ у TextWrangler і запускаю сценарій ще раз, перший сценарій знову отримує правильні змінні середовища від TextWrangler, але другий сценарій все ще має старі змінні середовища, якщо я раніше не вбив Термінал. Тож очевидно, що сеанс Terminal якось запам'ятовує перші змінні середовища, і не хоче оновити.
Але крім цього дуже елементарного розуміння, я не маю найменшого уявлення про те, як працюють змінні середовища, які сфери дії вони мають, і т. Д. Отже, хтось може пояснити, як я можу зробити так (якщо можливо, для початку), що другий скрипт знову також отримує правильні змінні середовища, не вбиваючи Термінал кожен раз?
Я намагався явно встановити змінні середовища в першому скрипті перед викликом exec()
, наприклад:
foreach( $_SERVER as $key => $value )
{
putenv( "$key=$value" );
}
exec( ... etc. );
Я намагався скасувати змінні середовища в кінці, як у першому, так і в другому сценаріях, як:
foreach( $_SERVER as $key => $value )
{
putenv( "$key" );
}
Але нічого не працює, як я очікував. Будь-які нові розуміння ретельно оцінили.
редагувати:
Тим часом я знайшов альтернативне, але незадовільне рішення: коли я дзвоню open -n -a Terminal ...
(зверніть увагу на доданий -n
аргумент) з exec()
, він щоразу запускає новий сеанс терміналу з правильними змінними середовища. Але це щоразу відкриває абсолютно новий екземпляр Терміналу.
оновлення:
Я трохи спростив процес, використовуючи лише один сценарій замість двох зараз, перевіривши змінну середовища SHLVL
. Я також встиг покінчити з новим екземпляром Terminal зараз, використовуючи тимчасовий файл, як і запропонував Скотт. Це призвело до наступного. Але я все ще відчуваю, що це не дуже елегантно.
$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" );
}
}
Отже, я все ще відкриваю занадто інші пропозиції (крім CLI та подаю пропозиції, які вже запропонував Скотт). Якщо, звичайно, це просто неможливо (Скотт, здавалося, вже натякає на це).
SHLVL
переданою, щоб побачити, чи є сценарій батьків чи дочір, і дійсно зберегти середовище у тимчасовому файлі, якщо він є батьківським, і читати таputenv()
-ing їх , якщо це дочірній сценарій. Але це не дуже елегантно. Ви впевнені, що крім кліпу чи файлу немає більш елегантного способу оновлення змінних оточення для одного і того ж сеансу терміналу?