Обновление переменных среды сеанса экрана для отображения нового графического входа в систему?

10664
Ryan Thompson

Я использую Linux, и мне нравится выполнять всю работу с командной строкой в ​​рамках одного сеанса экрана, чтобы я мог перезапустить свой графический вход в систему и тому подобное, не теряя свои терминалы. Однако, когда я выхожу из системы и возвращаюсь в свой графический сеанс, это меняет все переменные среды моего сеанса, такие как сеансы DBus. Это означает, что после повторного входа в систему мой экранный сеанс теперь имеет старые (и неправильные) переменные среды. Так что теперь, когда я пытаюсь запустить графические программы из моего сеанса экрана, в лучшем случае они выдают предупреждение о невозможности подключения к сеансовой шине. В худшем случае они не запускаются полностью.

Итак, я ищу способ изменения переменных окружения в работающем экземпляре экрана, чтобы все создаваемые впоследствии окна экрана наследовали новые переменные среды. Есть ли способ сделать это?

18
Ага! Я просто пролистал всю экранную справочную страницу, чтобы найти это: `setenv [var [string]] Установите переменную окружения var в значение string. Если указан только var, пользователю будет предложено ввести значение. Если параметры не указаны, пользователю будет предложено указать как переменную, так и значение. Окружающая среда наследуется всеми впоследствии разветвленными раковинами. Ryan Thompson 14 лет назад 2
Можно вызвать setenv, используя переключатель -X на экран. Увы, он работает только на всех впоследствии разветвленных оболочках, а не на текущей оболочке. Boris Bukh 12 лет назад 0
Обратите внимание, что [byobu] (http://byobu.co/) теперь включает решение для этого как для экрана, так и для tmux. Ryan Thompson 9 лет назад 0

3 ответа на вопрос

8
Benjamin Bannier

Вы не можете запустить сценарий оболочки из screenсеанса, так как он унаследует старую среду. Однако вы можете использовать fifo для добавления новых переменных среды в старый сеанс экрана. Вы можете заполнить этот fifo, когда начнете свой графический сеанс.

#!/bin/bash FIFO=/tmp/your_variables [ -e $FIFO ] && cat $FIFO > /dev/null || mkfifo $FIFO  # save number of variables that follow NVARS=2 echo $NVARS > $FIFO echo ENV1=sth1 > $FIFO echo ENV2=sth2 > $FIFO 

Запустите этот скрипт в фоновом режиме при входе в систему (он прекратит работу, когда все переменные будут считаны из него).

Теперь вы можете читать с fifo, например, добавить эту функцию в свой .bashrc

update_session() { FIFO=/tmp/your_variables  NVAR=$(cat $FIFO) for i in $(seq $NVAR); do export $(cat $FIFO) done #delete the pipe, or it will not work next time  rm $FIFO } 

так что вы можете в своей старой screenсессии

update_session 
Разве вам не нужно делать это один раз для каждого окна в текущем сеансе, чтобы изменить основную оболочку окна? quack quixote 14 лет назад 0
Хорошо, хотя, как говорит ~ quack, вам нужно обновлять каждую оболочку независимо. dmckee 14 лет назад 0
Правильно, вам нужно делать это в каждой оболочке `screen`. AFAIK `screen` не выставляет сокетов или подобных объектов для связи с запущенными сеансами извне. Benjamin Bannier 14 лет назад 0
@dmckee, но, конечно, каждый * новый * `экран` сеанс уже имеет последние переменные среды Benjamin Bannier 14 лет назад 0
Я решил просто принять этот ответ на данный момент. Если я когда-нибудь смогу реализовать это, я обновлю. Но пока достаточно просто иметь теплое нечеткое ощущение, что это теоретически возможно. Ryan Thompson 14 лет назад 0
2
Ryan Thompson

Я реализовал скрипт для этого. Вы можете получить его здесь: https://github.com/DarwinAwardWinner/screen-sendenv

После добавления screen-sendenv.pyв ваш $PATH, вы можете использовать следующий фрагмент в вашем .bashrc:

VARS_TO_UPDATE="DISPLAY DBUS_SESSION_BUS_ADDRESS SESSION_MANAGER GPG_AGENT_INFO" screen_pushenv () { screen-sendenv.py -t screen $VARS_TO_UPDATE } tmux_pushenv () { screen-sendenv.py -t tmux $VARS_TO_UPDATE } screen_pullenv () { tempfile=$(mktemp -q) && { for var in $VARS_TO_UPDATE; do screen sh -c "echo export $var=\$$var >> \"$tempfile\"" done . "$tempfile" rm -f "$tempfile" } } tmux_pullenv () { for var in $VARS_TO_UPDATE; do expr="$(tmux showenv | grep "^$var=")" if [ -n "$expr" ]; then export "$expr" fi done } 

Чтобы использовать его, просто запустите screen_pushenvперед тем, screen -rкак снова подключиться к экранной сессии. Затем, после подключения с screen -r, вы можете обновить среду в существующих оболочках с помощью screen_pullenv. Функции tmux выполняют то же самое для tmux, другого терминального мультиплексора, похожего на screen.

Вау, Райан, это много кода. Что не так с ранее принятым ответом (по крайней мере, вдохновляющим)? Benjamin Bannier 12 лет назад 0
Ну, я обнаружил, что screen (а также tmux) имеет команду «setenv», которая устанавливает переменную окружения для самого экрана, а не оболочки в текущем окне экрана. Таким образом, это означает, что после того, как вы используете мой сценарий, все вновь созданные окна в этом сеансе экрана будут автоматически получать новую среду без необходимости запускать сценарий обновления в каждом из них. Конечно, скрипт обновления все еще может быть полезен для обновления существующих оболочек, но вы должны переписать его не для чтения из FIFO, а для запроса новых значений самого сеанса screen / tmux. Ryan Thompson 12 лет назад 1
Вы можете увидеть, как получить переменные в текущую оболочку из сеанса screen / tmux [здесь] (http://bazaar.launchpad.net/~kirkland/byobu/trunk/view/head:/usr/bin/byobu-reconnect -sockets), в функциях `screen_update` и` tmux_update`. Я обновлю свой ответ независимой от них версией. Ryan Thompson 12 лет назад 0
В любом случае, чтобы прямо ответить на ваш вопрос о том, что было не так, ваш ответ не совсем отвечает на вопрос, а скорее отвечает на связанный вопрос. Вы показываете, как обновлять переменные среды внутри оболочки, работающей в сеансе экрана, но не как обновлять переменные среды в самом сеансе экрана (чтобы вновь созданные окна наследовали новые значения). Я принял это в то время, потому что это было все еще хорошее решение, но я всегда намеревался * в конечном счете * реализовать реальный ответ на мой вопрос * как задано *. Так что ничего личного. Ryan Thompson 12 лет назад 1
Привет Райан, спасибо за ответ. Теперь, когда вы упомянули `setenv`, я вижу, как это лучше. Это не было очевидно из кода, на который вы ссылались. Еще раз спасибо! Benjamin Bannier 12 лет назад 0
Мне пришлось добавить `sync` перед`. «$ tempfile» `для работы с домашними каталогами в NFS. drizzd 7 лет назад 0
0
wecac

This is probably a simpler solution (you decide). The important part being the alias that calls the savedisplay function every time screen command is run. The commands are not run automatically, hence can be put in ~/.bashrc instead of something very specialized like ~/.ssh/rc.

savedisplay() { # Write latest bash display to a file, This is used to # update running bash sessions for a "screen -r" echo "export DISPLAY=$DISPLAY" > ~/.XDISPLAY echo "export XAUTHORITY=$XAUTHORITY" >> ~/.XDISPLAY # This will only update the environment for new windows screen -X setenv DISPLAY $DISPLAY screen -X setenv XAUTHORITY $XAUTHORITY } # run this to update env variable in a running session updatedisplay() { source ~/.XDISPLAY } alias screen='savedisplay && screen' 

Похожие вопросы