Aggiornamento delle variabili di ambiente della sessione dello schermo per riflettere il nuovo accesso grafico?


20

Uso Linux e mi piace fare tutto il mio lavoro da riga di comando all'interno di una singola sessione dello schermo, in modo da poter riavviare il mio login grafico e simili senza perdere i miei terminali. Tuttavia, quando esco e torno alla mia sessione grafica, questo cambia tutte le variabili di ambiente della mia sessione, come le sessioni DBus. Ciò significa che dopo aver effettuato nuovamente l'accesso, la mia sessione di schermo ora ha le variabili di ambiente vecchie (e errate). Quindi ora quando provo ad avviare programmi grafici dalla mia sessione dello schermo, nella migliore delle ipotesi emettono un avviso di non essere in grado di connettersi al bus di sessione. Nel peggiore dei casi, non si avviano completamente.

Quindi, quello che sto cercando è un modo per modificare le variabili di ambiente in un'istanza di schermo in esecuzione, in modo che tutte le finestre di schermo create successivamente ereditino le nuove variabili di ambiente. C'è un modo per fare questo?


3
Aha! Ho appena sfogliato l'intera manpage dello schermo per trovare questo: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,

Si può invocare setenv usando -X per passare allo schermo. Ahimè, funziona solo su tutte le shell biforcute successivamente, non sulla shell corrente.
Boris Bukh,

Si noti che byobu ora incorpora una soluzione per questo sia per schermo che per tmux.
Ryan C. Thompson,

Risposte:


8

Non è possibile avviare uno script di shell dalla screensessione poiché erediterebbe il vecchio ambiente. Puoi comunque noi un quindicesimo per ottenere le nuove variabili di ambiente nella vecchia sessione dello schermo. Puoi riempire quel quindicesimo quando inizi la tua sessione grafica.

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

Avvia lo script in background all'accesso (termina solo quando tutte le variabili vengono lette da esso).

Ora puoi leggere dal Fifo, ad esempio aggiungi questa funzione alla tua .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
}

così puoi farlo nella tua vecchia screensessione

update_session

non dovresti farlo una volta per finestra nella sessione in esecuzione per modificare la shell principale della finestra?
Quack Quixote

Bello, anche se come dice ~ quack, devi aggiornare ogni shell in modo indipendente.
dmckee,

Bene, devi farlo in ogni shell in screen. AFAIK screennon espone socket o simili per comunicare con sessioni in esecuzione dall'esterno.
Benjamin Bannier,

@dmckee ma ovviamente ogni nuova screen sessione ha già le recenti variabili d'ambiente
Benjamin Bannier

Ho deciso di accettare questa risposta per ora. Se mai riuscissi a implementarlo, lo aggiornerò. Ma per ora, è sufficiente solo avere una calda sensazione confusa di sapere che è teoricamente possibile.
Ryan C. Thompson,

2

Ho implementato una sceneggiatura per farlo. Puoi ottenerlo qui: https://github.com/DarwinAwardWinner/screen-sendenv

Dopo averlo screen-sendenv.pyinserito nel tuo $PATH, puoi usare il seguente frammento nel tuo .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
}

Per usarlo, basta eseguire screen_pushenvprima di eseguire screen -rper ricollegarsi alla sessione dello schermo. Quindi, dopo aver effettuato il collegamento con screen -r, è possibile aggiornare l'ambiente nelle shell esistenti con screen_pullenv. Le funzioni di tmux realizzano la stessa cosa per tmux, un altro multiplexer terminale simile allo schermo.


Wow Ryan, questo è un sacco di codice. Cosa c'era di sbagliato nella risposta precedentemente accettata (almeno ispirava)?
Benjamin Bannier,

1
Bene, ho scoperto che screen (e anche tmux) hanno un comando "setenv" che imposta una variabile d'ambiente per lo schermo stesso, non la shell nella finestra corrente dello schermo. Ciò significa che dopo aver utilizzato il mio script, tutte le finestre appena create in quella sessione dello schermo otterranno automaticamente il nuovo ambiente, senza dover eseguire lo script di aggiornamento in ognuno di essi. Naturalmente, uno script di aggiornamento potrebbe ancora essere utile per l'aggiornamento delle shell esistenti, ma è necessario riscriverlo non per leggere da un FIFO, ma per interrogare la sessione screen / tmux stessa per i nuovi valori.
Ryan C. Thompson,

Puoi vedere come estrarre le variabili nella shell corrente dalla sessione screen / tmux qui , nelle funzioni screen_updatee tmux_update. Aggiornerò la mia risposta con una versione indipendente da byobu di questi.
Ryan C. Thompson,

1
Ad ogni modo, per rispondere direttamente alla tua domanda su ciò che era sbagliato, la tua risposta non risponde completamente alla domanda, ma risponde piuttosto a una domanda correlata. Si mostra come aggiornare le variabili di ambiente all'interno di una shell in esecuzione all'interno di una sessione dello schermo, ma non come aggiornare le variabili di ambiente nella stessa sessione dello schermo (in modo tale che le finestre appena generate ereditino i nuovi valori). Ho accettato, al momento perché era ancora una buona soluzione, ma avevo sempre inteso finalmente attuare una vera risposta alla mia domanda come chiesto . Quindi, niente di personale.
Ryan C. Thompson,

Ehi Ryan, grazie per aver risposto. Ora che hai menzionato, setenvvedo come sia meglio. Non era ovvio dal codice a cui ti sei collegato. Grazie ancora!
Benjamin Bannier,

2

È possibile richiamare il setenvcomando per modificare le variabili di ambiente nel processo di schermata in modo interattivo, utilizzando: Ctrl- A+ :setenv(Nota il :carattere per immettere un comando di schermata.) Verrà richiesto il nome e il valore della variabile di ambiente.

Si noti che (come per altre risposte / commenti) ciò influisce sul processo dello schermo (padre) e quindi sulle sessioni dello schermo appena create, ma non sulla sessione dello schermo corrente né su eventuali sessioni dello schermo esistenti.

È possibile specificare il nome e il valore della variabile di ambiente contemporaneamente se si desidera: Ctrl- A+ :setenv DISPLAY :100. Imposterà il DISPLAY su ": 100" per le nuove sessioni dello schermo.

Per rimuovere una variabile d'ambiente puoi usare 'unsetenv' - es. Ctrl- A+:unsetenv DISPLAY


0

Questa è probabilmente una soluzione più semplice (decidi tu). La parte importante è l'alias che chiama la savedisplayfunzione ogni volta che screenviene eseguito il comando. I comandi non vengono eseguiti automaticamente, quindi possono essere inseriti ~/.bashrcinvece di qualcosa di molto specializzato ~/.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'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.