1 added
1 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Я насчитал 10 способов запуска. И три разных 'echo' на одной убунте. И узнал некоторые трюки. Пока искал, как перекинуть изменённую переменную из дочернего процесса в родительский.</p>
1
<p>Я насчитал 10 способов запуска. И три разных 'echo' на одной убунте. И узнал некоторые трюки. Пока искал, как перекинуть изменённую переменную из дочернего процесса в родительский.</p>
2
<h2>Содержание</h2>
2
<h2>Содержание</h2>
3
<ul><li><a>Встраивание сценария в текущий процесс bash</a></li>
3
<ul><li><a>Встраивание сценария в текущий процесс bash</a></li>
4
<li><a>Запуск дочернего процесса</a></li>
4
<li><a>Запуск дочернего процесса</a></li>
5
<li><a>Какие ещё способы запуска?</a></li>
5
<li><a>Какие ещё способы запуска?</a></li>
6
<li><a>echo</a></li>
6
<li><a>echo</a></li>
7
<li><a>Записать переменную в файл</a></li>
7
<li><a>Записать переменную в файл</a></li>
8
<li><a>printenv</a></li>
8
<li><a>printenv</a></li>
9
</ul><h2>Встраивание сценария в текущий процесс bash</h2>
9
</ul><h2>Встраивание сценария в текущий процесс bash</h2>
10
<p>Когда мы вызываем скрипт из терминала - то этот скрипт становится отдельным процессом, дочерним от процесса терминала. Он наследует все переменные среды, которые были объявлены через export $VAR (а не просто $VAR - простые не будут видны.) Когда этот дочерний скрипт изменяет унаследованную переменную - эта переменная уже его лично, в родительском процессе значение переменной не меняется. Надёжный способ передать из дочернего процесса в родительский какую-то инфу - это возвратить какие-то результаты, как из функции, или послать вывод дочерней функции в пайп.</p>
10
<p>Когда мы вызываем скрипт из терминала - то этот скрипт становится отдельным процессом, дочерним от процесса терминала. Он наследует все переменные среды, которые были объявлены через export $VAR (а не просто $VAR - простые не будут видны.) Когда этот дочерний скрипт изменяет унаследованную переменную - эта переменная уже его лично, в родительском процессе значение переменной не меняется. Надёжный способ передать из дочернего процесса в родительский какую-то инфу - это возвратить какие-то результаты, как из функции, или послать вывод дочерней функции в пайп.</p>
11
<p>bash ввёл такую тему: "встраивание" кода, прочитанного из другого файла прямо в текущий процесс. Файл не обязан быть исполняемым, а по правилам хорошего тона - его таким и не делают.</p>
11
<p>bash ввёл такую тему: "встраивание" кода, прочитанного из другого файла прямо в текущий процесс. Файл не обязан быть исполняемым, а по правилам хорошего тона - его таким и не делают.</p>
12
<p>Примеры таких команд:</p>
12
<p>Примеры таких команд:</p>
13
<p>Это позволяет исполнить посторонний код, он обновляет переменные, а текущий процесс этим пользуется. Если бы посторонний код был запущен как дочерний - это не получилось бы. Если подключаемы скрипт захочет навредить - он навредит. Если в нём exit - то весь процесс закроется, не отработав до конца.</p>
13
<p>Это позволяет исполнить посторонний код, он обновляет переменные, а текущий процесс этим пользуется. Если бы посторонний код был запущен как дочерний - это не получилось бы. Если подключаемы скрипт захочет навредить - он навредит. Если в нём exit - то весь процесс закроется, не отработав до конца.</p>
14
<p>В подключаемом скрипте могут быть только переменные и функции - тогда переменные запишутся в текущее окружение, а функции будут доступны для вызова. Если и в текущем и в новом скрипте есть функции с одинаковым именем - нужно сперва текущую переназвать declare -f new_function_name=old_function_name, а потом делать вставку source side_bashcode.</p>
14
<p>В подключаемом скрипте могут быть только переменные и функции - тогда переменные запишутся в текущее окружение, а функции будут доступны для вызова. Если и в текущем и в новом скрипте есть функции с одинаковым именем - нужно сперва текущую переназвать declare -f new_function_name=old_function_name, а потом делать вставку source side_bashcode.</p>
15
<p>Говорят, что ради возможности загрузить переменные из посторонних источников это и сделали. Ради того, чтоб у каждого пользователя был свой личный .profile (вызывается при логине) и .bashrc (вызывается при создании терминала). Это не синонимы. Окошко с терминалом можно закрыть, или открыть второе - .bashrc прочтётся заново. Даже без GUI - команда exec $SHELL делает то же самое, заставляет заменить текущий процесс командной оболочки на новый процесс, возможно даже на другое приложение. Оно запустится с нуля, как будто после логина. Но без самого логина, без перезагрузки .profile. Зато перезагрузится .bashrc.</p>
15
<p>Говорят, что ради возможности загрузить переменные из посторонних источников это и сделали. Ради того, чтоб у каждого пользователя был свой личный .profile (вызывается при логине) и .bashrc (вызывается при создании терминала). Это не синонимы. Окошко с терминалом можно закрыть, или открыть второе - .bashrc прочтётся заново. Даже без GUI - команда exec $SHELL делает то же самое, заставляет заменить текущий процесс командной оболочки на новый процесс, возможно даже на другое приложение. Оно запустится с нуля, как будто после логина. Но без самого логина, без перезагрузки .profile. Зато перезагрузится .bashrc.</p>
16
<p>Оригинальный, более старый и "совместимый со всеми" shell (sh), похоже, такого не умеет.</p>
16
<p>Оригинальный, более старый и "совместимый со всеми" shell (sh), похоже, такого не умеет.</p>
17
<h2>Запуск дочернего процесса</h2>
17
<h2>Запуск дочернего процесса</h2>
18
<p>Это "обычный" запуск. Когда запускаем скрипт по имени, или приложение - то "родительская" (та, из которой исходит команда) прилога создаёт копию своего процесса, грузит в процесс код из запускаемого приложения, и "передаёт управление" = прекращает посылать команды, начинает с команды новой прилоги, которая описана как "точка входа". Примеры:</p>
18
<p>Это "обычный" запуск. Когда запускаем скрипт по имени, или приложение - то "родительская" (та, из которой исходит команда) прилога создаёт копию своего процесса, грузит в процесс код из запускаемого приложения, и "передаёт управление" = прекращает посылать команды, начинает с команды новой прилоги, которая описана как "точка входа". Примеры:</p>
19
<p>Чтобы вызвать так, нужно поставить разрешение "execute". Если это не машкод, а текст - в нём указать первой строкой #!/path/to/interpreter. Если хочешь вызывать его из любого каталога - добавь его в одну из папок $PATH, или папку с ним добавь в $PATH. Вуаля, системная команда, как у взрослых!</p>
19
<p>Чтобы вызвать так, нужно поставить разрешение "execute". Если это не машкод, а текст - в нём указать первой строкой #!/path/to/interpreter. Если хочешь вызывать его из любого каталога - добавь его в одну из папок $PATH, или папку с ним добавь в $PATH. Вуаля, системная команда, как у взрослых!</p>
20
<p>Дочка может унаследовать права от матери. Если найдёт себе материнский процесс, работающий под именем root, и тот позволит отпочковаться с теми же правами - вау, у процесса права на всё!</p>
20
<p>Дочка может унаследовать права от матери. Если найдёт себе материнский процесс, работающий под именем root, и тот позволит отпочковаться с теми же правами - вау, у процесса права на всё!</p>
21
<h2>Какие ещё способы запуска?</h2>
21
<h2>Какие ещё способы запуска?</h2>
22
<p>Вариант с двумя файлами:</p>
22
<p>Вариант с двумя файлами:</p>
23
<p>& в конце - он позволит форкнуть процесс и тут же отключить его от терминала. Процесс работает сам по себе, а мы его не ждём, можем вводить новые команды или запускать параллельные процессы.</p>
23
<p>& в конце - он позволит форкнуть процесс и тут же отключить его от терминала. Процесс работает сам по себе, а мы его не ждём, можем вводить новые команды или запускать параллельные процессы.</p>
24
<h2>echo</h2>
24
<h2>echo</h2>
25
<p>Внимейшн! Я узнал три варианта echo:</p>
25
<p>Внимейшн! Я узнал три варианта echo:</p>
26
<ul><li>echo в sh - команда, которая не понимает опции -e (она её просто печатает как будто это целевой текст), но зато понимает, что \n (и другие эскейпы) нужно превращать в спецсимволы;</li>
26
<ul><li>echo в sh - команда, которая не понимает опции -e (она её просто печатает как будто это целевой текст), но зато понимает, что \n (и другие эскейпы) нужно превращать в спецсимволы;</li>
27
<li>echo в bash - команда, которая без опции -e не превращает \n и другие эскейпы, ей нужно прямо заказать опцию -e - и тогда начнёт превращать;</li>
27
<li>echo в bash - команда, которая без опции -e не превращает \n и другие эскейпы, ей нужно прямо заказать опцию -e - и тогда начнёт превращать;</li>
28
<li>echo в GNU utilites - вообще самостоятельная прилога, у неё тоже какие-то особенности.</li>
28
<li>echo в GNU utilites - вообще самостоятельная прилога, у неё тоже какие-то особенности.</li>
29
</ul><p>В общем, советы в интернете противоречат друг другу, проще прочитать man echo о том варианте, который используете вы.</p>
29
</ul><p>В общем, советы в интернете противоречат друг другу, проще прочитать man echo о том варианте, который используете вы.</p>
30
<h2>Записать переменную в файл</h2>
30
<h2>Записать переменную в файл</h2>
31
<p>Попроще:</p>
31
<p>Попроще:</p>
32
<p>Эти ответы не сработают, если текст:</p>
32
<p>Эти ответы не сработают, если текст:</p>
33
<ul><li>начинается с -e, или с -n, или с -E</li>
33
<ul><li>начинается с -e, или с -n, или с -E</li>
34
<li>или содержит \n</li>
34
<li>или содержит \n</li>
35
<li>не должен заканчиваться переводом строки, когда будет записан в файл.</li>
35
<li>не должен заканчиваться переводом строки, когда будет записан в файл.</li>
36
-
</ul><p>Что тогда поможет?</p>
36
+
</ul><p>��то тогда поможет?</p>
37
<h2>printenv</h2>
37
<h2>printenv</h2>
38
<p>Я видел одно упоминание этой команды, а команда есть!</p>
38
<p>Я видел одно упоминание этой команды, а команда есть!</p>
39
<h3><a>Переменные в bash</a></h3>
39
<h3><a>Переменные в bash</a></h3>