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


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.