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


20

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

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


3
Ага! Я просто пролистал всю экранную справочную страницу, чтобы найти это:setenv [var [string]] Set the environment variable var to value string. If only var is specified, the user will be prompted to enter a value. If no parameters are specified, the user will be prompted for both variable and value. The environment is inherited by all subsequently forked shells.
Райан С. Томпсон

Можно вызвать setenv, используя переключатель -X на экран. Увы, он работает только на всех впоследствии разветвленных оболочках, а не на текущей оболочке.
Борис Бух

Обратите внимание, что в byobu теперь есть решение для экрана и tmux.
Райан К. Томпсон

Ответы:


8

Вы не можете запустить сценарий оболочки из 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, вам нужно обновлять каждую оболочку независимо.
dmckee

Правильно, вам нужно делать это в каждой оболочке screen. AFAIK не screenпредоставляет никаких сокетов или подобных устройств для связи с запущенными сеансами извне.
Бенджамин Банье

@dmckee, но, конечно, в каждой новой screen сессии уже есть последние переменные среды
Бенджамин Банье

Я решил просто принять этот ответ на данный момент. Если я когда-нибудь смогу реализовать это, я обновлю. Но пока достаточно просто иметь теплое нечеткое ощущение, что это теоретически возможно.
Райан К. Томпсон

2

Я реализовал скрипт для этого. Вы можете получить его здесь: 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.


Вау, Райан, это много кода. Что не так с ранее принятым ответом (по крайней мере, вдохновляющим)?
Бенджамин Банье

1
Ну, я обнаружил, что screen (а также tmux) имеет команду «setenv», которая устанавливает переменную окружения для самого экрана, а не оболочки в текущем окне экрана. Таким образом, это означает, что после того, как вы используете мой сценарий, все вновь созданные окна в этом сеансе экрана автоматически получат новую среду без необходимости запускать сценарий обновления в каждом из них. Конечно, скрипт обновления все еще может быть полезен для обновления существующих оболочек, но вы должны переписать его не для чтения из FIFO, а для запроса новых значений в самом сеансе screen / tmux.
Райан К. Томпсон

Вы можете увидеть , как вывести переменные в текущую оболочку из экрана / tmux сессии здесь , в screen_updateи tmux_updateфункциях. Я обновлю свой ответ независимой от них версией этого.
Райан К. Томпсон

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

Эй, Райан, спасибо за ответ. Теперь, когда вы упомянули, setenvя вижу, как это лучше. Это не было очевидно из кода, на который вы ссылались. Еще раз спасибо!
Бенджамин Банье

2

Вы можете вызвать setenvкоманду, чтобы изменить переменные среды в процессе экрана в интерактивном режиме, используя: Ctrl- A+ :setenv(запишите :символ для ввода команды экрана.) Вам будет предложено ввести имя и значение переменной среды.

Обратите внимание, что (как и в других ответах / комментариях) это влияет на (родительский) процесс экрана и, следовательно, на вновь созданные сеансы экрана, но не на текущий сеанс экрана или на существующие сеансы экрана.

Вы можете указать имя и значение переменной среды одновременно, если хотите: Ctrl- A+ :setenv DISPLAY :100. Установите для DISPLAY значение «: 100» для новых сеансов экрана.

Чтобы удалить переменную окружения, вы можете использовать 'unsetenv' - например, Ctrl- A+:unsetenv DISPLAY


0

Это, вероятно, более простое решение (вы решаете). Важной частью является псевдоним, который вызывает savedisplayфункцию при каждом screenзапуске команды. Команды не запускаются автоматически, поэтому могут быть вставлены ~/.bashrcвместо чего-то очень специализированного, например ~/.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'
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.