HTML Diff
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>&amp; в конце - он позволит форкнуть процесс и тут же отключить его от терминала. Процесс работает сам по себе, а мы его не ждём, можем вводить новые команды или запускать параллельные процессы.</p>
23 <p>&amp; в конце - он позволит форкнуть процесс и тут же отключить его от терминала. Процесс работает сам по себе, а мы его не ждём, можем вводить новые команды или запускать параллельные процессы.</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>