Оновлення змінних середовищ екранного сеансу для відображення нового графічного входу?


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сеансу, оскільки він успадкує старе середовище. Тим не менш, ти можеш використати фіфо, щоб отримати нові змінні середовища в старий сеанс екрана. Ви можете заповнити цей файл, коли розпочнете графічний сеанс.

#!/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

Почніть цей скрипт у фоновому режимі при вході (він закінчиться лише тоді, коли з нього будуть прочитані всі змінні).

Тепер ви можете прочитати з файлу, наприклад, додати цю функцію до своєї програми .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, іншого термінального мультиплексора, схожого на екран.


Вау Раян, це дуже багато коду. Що було не так із раніше прийнятою відповіддю (це надихало принаймні)?
Бенджамін Баньє

1
Ну, я виявив, що екран (а також 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.