Необычайно простой вопрос написания сценариев для оболочки: вносить изменения? - PullRequest
1 голос
/ 27 марта 2009

Я пишу сценарии оболочки для различных действий в OSX и Linux, но у меня всегда одна и та же проблема. Скрипт запускается, но любые изменения, которые он вносит в среду (кроме дисков, конечно), не "прилипают". Когда скрипт завершает работу, изменения возвращаются.

Как я могу сделать мои изменения палкой?

Редактировать: Многие ответы были великолепны, но они не помогли ситуации, с которой я столкнулся сегодня вечером. Я пытаюсь запустить это, чтобы заставить мой интерфейс TAP работать

sudo bash # we go superuser
exec 4<>/dev/tap0  # opens device, creates interface tap0
ifconfig tap0 10.10.10.1 10.10.10.255
ifconfig tap0 up 

, который прекрасно работает, если я вставлю его, но не если я его получу или покажу. Кстати, я не могу закрыть окно терминала после этого, как тогда я теряю интерфейс tap0.

Последнее редактирование: Спасибо всем, ответ состоял в том, чтобы использовать source, как вы все предложили, но удалить команду sudo из самого скрипта.

Ответы [ 7 ]

4 голосов
/ 27 марта 2009

Такое поведение разработано - по крайней мере, в bash, что я и использую, но я думаю, что большинство оболочек работают одинаково. В общем случае процесс не может экспортировать такие вещи, как переменные среды, в свой родительский процесс. Если вы хотите выполнить серию команд для изменения среды в текущем процессе оболочки, вы можете записать команды в файл и source it. В bash вы наберете

$ source commands.sh

или

$ . commands.sh
3 голосов
/ 27 марта 2009

Изменения среды в дочернем процессе не влияют на родительский процесс. К счастью, вы можете запустить скрипт оболочки в текущем процессе, сказав

. /path/to/script.sh

или

source /path/to/script.sh

Будьте осторожны, если вы запустите exit в скрипте, он выйдет из текущей оболочки.

2 голосов
/ 27 марта 2009

Если вы устанавливаете переменные среды в вашем скрипте, они будут зависать только во время выполнения вашего скрипта.

Если вам нужны переменные окружения для всего сеанса оболочки, вам необходимо установить их в файле .profile, .bashrc, .tcshrc или .rc для любой используемой вами оболочки. См. "man <your shell>" (например, man bash) для примеров того, как это сделать.

2 голосов
/ 27 марта 2009

Вы имеете в виду «окружение» как в переменных окружения? Вы не можете, не так, как вы имеете в виду. Эта «среда» - это вещь, связанная с контекстом процесса; это не глобально для вашей системы, это часть конкретной среды выполнения скрипта. Он может быть передан процессам запуска скрипта, но это все. Если вы хотите установить надежные настройки для переменных среды, вы должны сделать это в общих системных файлах инициализации, таких как / etc / profile и /etc/bash.bashrc (фактические имена ОС и зависимости от установки). Различные сценарии инициализации запускаются при разных обстоятельствах (оболочки входа в систему или порожденные оболочки и тому подобное), но идея заключается в том, что вы предварительно инициализируете оболочки с любым контекстом среды, который хотите всегда иметь вокруг.

1 голос
/ 27 марта 2009

Когда вы используете sudo, вы должны понимать, что вы запускаете другую программу, в данном случае другую оболочку. Это недоразумение, что вставка этих команд в терминале была бы такой же, как вставка их в сценарий. В результате после sudo терминал подключается к другому сеансу оболочки, а вторая и последующие команды отправляются в этот другой сеанс оболочки. Если вы поместите все команды в сценарий, все четыре команды будут выполнены в одном сеансе оболочки, что приведет к нежелательным результатам.

В этом конкретном случае я предлагаю вам поместить три последние команды в другой скрипт (например, setup-tap.sh), а затем вызвать этот скрипт как

sudo bash setup-tap.sh

Sourcing, как и предполагалось, является альтернативой для сохранения изменений вызова скрипта в текущей оболочке, но в этом случае он не будет работать. Он на один уровень выше, он может выглядеть как сценарий, поскольку терминал такой же, но в результате после sudo вы уже не в той же оболочке.

Это похоже на сценарий, подобный следующему:

vi file.txt
iThe quick brown fox jumps over the lazy dog.<ESC>:wq

Конечно, вторая строка (команды vi) не будет набрана в vi, она все равно будет в исходном скрипте.

Другой вариант - использовать здесь-документы и передавать привилегированные команды в sudo bash из стандартного ввода:

sudo bash <<-EOF
  exec 4<>/dev/tap0
  ifconfig tap0 10.10.10.1 10.10.10.255
  ifconfig tap0 up
EOF
1 голос
/ 27 марта 2009

Ваш реальный вопрос, похоже, касается только интерфейса крана. Вы должны изменить вопрос, чтобы отразить это.

Прочтите документацию о tap из документации Linux / networking / tuntap.txt. Вот короткая цитата:

"Чтобы использовать драйвер, программа должна открыть / dev / net / tun и выпустить соответствующий ioctl () для регистрации сетевого устройства с ядром. Сеть Устройство будет отображаться как tunXX или tapXX, в зависимости от выбранных параметров. когда программа закрывает дескриптор файла , сетевое устройство и все соответствующие маршруты исчезнут. "

Довольно просто, я бы сказал. Ничего загадочного в этом нет. Ваш скрипт открывает интерфейс крана, и когда скрипт выходит из него, закрывает дескриптор файла .

1 голос
/ 27 марта 2009

Это по замыслу.

Вы можете записать нужные переменные окружения в файл и прочитать их при следующем запуске. Например:

#!/bin/sh

# load from ~/.my_env
[ -r ~/.my_env ] && . ~/.my_env

# replace or add new entries to ~/.my_env
for i in "$@"; do
    [ "${i/=/}" = "$i" ] && continue
    touch ~/.my_env
    sed -i -e "\|^export ${i%%=*}=|d" ~/.my_env
    echo "export $i" >> ~/.my_env
    eval export "$i"
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...