Я витягаю волосся, намагаючись зрозуміти сценарій оболонки та прохідні змінні середовища, а що ні.
Я намагаюся виконати скрипт 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 їх , якщо це дочірній сценарій. Але це не дуже елегантно. Ви впевнені, що крім кліпу чи файлу немає більш елегантного способу оновлення змінних оточення для одного і того ж сеансу терміналу?