Aktualizujesz zmienne środowiskowe sesji ekranowej, aby odzwierciedlić nowy graficzny login?

20

Korzystam z systemu Linux i lubię wykonywać całą pracę z wierszem poleceń w ramach sesji jednego ekranu, aby móc ponownie uruchomić logowanie graficzne i tym podobne, bez utraty terminali. Jednak wylogowanie i powrót do sesji graficznej powoduje zmianę wszystkich zmiennych środowiskowych sesji, takich jak sesje DBus. Oznacza to, że po ponownym zalogowaniu moja sesja screen ma teraz stare (i złe) zmienne środowiskowe. Więc teraz, kiedy próbuję uruchomić programy graficzne z sesji ekranowej, w najlepszym wypadku wysyłają ostrzeżenie o niemożności połączenia z magistralą sesji. W najgorszym przypadku nie zaczynają całkowicie.

Tak więc szukam sposobu na zmodyfikowanie zmiennych środowiskowych w działającej instancji screen, aby wszystkie później utworzone okna ekranowe odziedziczyły nowe zmienne środowiskowe. Czy jest na to sposób?

Ryan C. Thompson
źródło
3
Aha! Właśnie przeszukałem stronę podręczną całego ekranu, aby znaleźć to: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.
Ryan C. Thompson
Można wywołać setenv za pomocą przełącznika -X na ekran. Niestety, działa tylko na wszystkie kolejne rozwidlone powłoki, a nie na bieżącą powłokę.
Boris Bukh,
Zauważ, że byobu zawiera teraz rozwiązanie dla tego ekranu i tmux.
Ryan C. Thompson,

Odpowiedzi:

8

Nie można uruchomić skryptu powłoki z screensesji, ponieważ odziedziczy on stare środowisko. Możesz jednak nam pomóc, aby wprowadzić nowe zmienne środowiskowe do starej sesji ekranowej. Możesz wypełnić tę piątkę po rozpoczęciu sesji graficznej.

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

Uruchom ten skrypt w tle przy logowaniu (zakończy się dopiero po odczytaniu z niego wszystkich zmiennych).

Teraz możesz czytać z FIFO, np. Dodaj tę funkcję do swojego .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
}

abyś mógł podczas swojej starej screensesji

update_session
Benjamin Bannier
źródło
czy nie musisz tego robić raz na okno w uruchomionej sesji, aby zmodyfikować główną powłokę okna?
szarlatan
Fajnie, choć jak mówi ~ quack, musisz aktualizować każdą powłokę niezależnie.
dmckee,
Racja, musisz to zrobić w każdej powłoce screen. AFAIK screennie ujawnia żadnych gniazd ani podobnych elementów do komunikacji z uruchomionymi sesjami z zewnątrz.
Benjamin Bannier
@dmckee, ale oczywiście każda nowa screen sesja ma już najnowsze zmienne środowiskowe
Benjamin Bannier
Postanowiłem na razie zaakceptować tę odpowiedź. Jeśli kiedykolwiek uda mi się wdrożyć to, zaktualizuję. Ale na razie wystarczy mieć ciepłe, rozmyte uczucie, wiedząc, że teoretycznie jest to możliwe.
Ryan C. Thompson,
2

W tym celu zaimplementowałem skrypt. Możesz go pobrać tutaj: https://github.com/DarwinAwardWinner/screen-sendenv

Po włożeniu screen-sendenv.pydo $PATHswojego pliku .bashrc możesz użyć następującego fragmentu kodu:

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
}

Aby z niego skorzystać, po prostu uruchom screen_pushenvprzed uruchomieniem, screen -raby ponownie dołączyć do sesji ekranu. Następnie, po dołączeniu za pomocą screen -r, możesz zaktualizować środowisko w swoich istniejących powłokach za pomocą screen_pullenv. Funkcje tmux osiągają to samo dla tmux, innego terminalowego multipleksera podobnego do screena.

Ryan C. Thompson
źródło
Wow Ryan, to dużo kodu. Co było nie tak z poprzednio przyjętą odpowiedzią (przynajmniej była inspirująca)?
Benjamin Bannier
1
Odkryłem, że screen (a także tmux) ma polecenie „setenv”, które ustawia zmienną środowiskową dla samego screena, a nie powłokę w bieżącym oknie screena. Oznacza to, że po użyciu mojego skryptu wszystkie nowo utworzone okna w tej sesji ekranowej automatycznie otrzymają nowe środowisko bez konieczności uruchamiania skryptu aktualizacji w każdym z nich. Oczywiście skrypt aktualizacji może nadal być przydatny do aktualizowania istniejących powłok, ale trzeba go przepisać, aby nie czytać z FIFO, ale zapytać samą sesję screen / tmux o nowe wartości.
Ryan C. Thompson
Możesz zobaczyć, jak pobrać zmienne do bieżącej powłoki z sesji screen / tmux tutaj , w funkcjach screen_updatei tmux_update. Zaktualizuję moją odpowiedź za pomocą niezależnej od byobu wersji.
Ryan C. Thompson
1
W każdym razie, aby bezpośrednio odpowiedzieć na pytanie o to, co było nie tak, twoja odpowiedź nie odpowiada na pytanie, ale raczej odpowiada na powiązane pytanie. Pokazujesz, jak zaktualizować zmienne środowiskowe w powłoce działającej w sesji ekranowej, ale nie wiesz, jak zaktualizować zmienne środowiskowe w samej sesji ekranowej (tak, aby nowo powstałe okna dziedziczyły nowe wartości). Zaakceptowałem to wtedy, ponieważ wciąż było to dobre rozwiązanie, ale zawsze zamierzałem w końcu wprowadzić prawdziwą odpowiedź na zadane pytanie . Nic osobistego.
Ryan C. Thompson
Hej Ryan, dzięki za odpowiedź. Teraz, setenvkiedy wspomniałeś , widzę, jak to jest lepsze. Nie było to oczywiste z kodu, z którym się łączyłeś. Dzięki jeszcze raz!
Benjamin Bannier
2

Możesz wywołać setenvpolecenie w celu interaktywnej zmiany zmiennych środowiskowych w procesie ekranowym, używając: Ctrl- A+ :setenv(Uwaga na :znak, aby wprowadzić polecenie ekranowe.) Zostaniesz poproszony o podanie nazwy i wartości zmiennej środowiskowej.

Zauważ, że (jak w przypadku innych odpowiedzi / komentarzy) wpływa to na proces (rodzicielski) ekranu, a zatem nowo utworzone sesje ekranu, ale nie na bieżącą sesję ekranu ani na żadne istniejące sesje ekranu.

Możesz podać nazwę i wartość zmiennej środowiskowej jednocześnie, jeśli chcesz: Ctrl- A+ :setenv DISPLAY :100. Ustawi WYŚWIETLACZ na „: 100” dla nowych sesji ekranu.

Aby usunąć zmienną środowiskową, możesz użyć „unsetenv” - np. Ctrl- A+:unsetenv DISPLAY

Pan Łasica
źródło
0

Jest to prawdopodobnie prostsze rozwiązanie (decydujesz). Ważną częścią jest alias, który wywołuje savedisplayfunkcję przy każdym uruchomieniu screenpolecenia. Polecenia nie są uruchamiane automatycznie, dlatego można je wprowadzić ~/.bashrczamiast czegoś bardzo specjalistycznego ~/.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'
wecac
źródło