Memperbarui variabel lingkungan sesi layar untuk mencerminkan login grafis baru?


20

Saya menggunakan linux, dan saya suka melakukan semua pekerjaan baris perintah saya dalam satu sesi layar, sehingga saya bisa memulai kembali login grafis saya dan semacamnya tanpa kehilangan terminal saya. Namun, ketika saya keluar dan kembali ke sesi grafis saya, ini mengubah semua variabel lingkungan sesi saya, seperti sesi DBus. Ini berarti bahwa setelah masuk lagi, sesi layar saya sekarang memiliki variabel lingkungan lama (dan salah). Jadi sekarang ketika saya mencoba untuk memulai program grafis dari sesi layar saya, paling-paling mereka memancarkan peringatan tentang tidak dapat terhubung ke bus sesi. Paling buruk, mereka gagal memulai sepenuhnya.

Jadi, apa yang saya cari adalah cara untuk memodifikasi variabel lingkungan dalam instance layar yang sedang berjalan, sehingga semua jendela layar yang dibuat selanjutnya akan mewarisi variabel lingkungan baru. Apakah ada cara untuk melakukan ini?


3
Aha! Saya baru saja menelusuri halaman seluruh layar untuk menemukan ini: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

Satu dapat memanggil setenv menggunakan -X beralih ke layar. Sayangnya, ini hanya bekerja pada semua cangkang yang kemudian bercabang, bukan pada cangkang saat ini.
Boris Bukh

Perhatikan bahwa byobu sekarang memasukkan solusi untuk ini untuk layar dan tmux.
Ryan C. Thompson

Jawaban:


8

Anda tidak dapat memulai skrip shell dari screensesi karena akan mewarisi lingkungan lama. Namun Anda dapat menggunakan fifo untuk memasukkan variabel lingkungan baru ke dalam sesi layar lama. Anda dapat mengisi fifo itu saat memulai sesi grafis Anda.

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

Mulai skrip itu di latar belakang saat login (itu hanya akan berakhir ketika semua variabel dibaca dari itu).

Sekarang Anda dapat membaca dari fifo, mis. Tambahkan fungsi ini ke .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
}

sehingga Anda bisa di screensesi lama Anda

update_session

tidakkah Anda perlu melakukan ini sekali per jendela dalam sesi berjalan untuk memodifikasi shell utama jendela?
quack quixote

Bagus, meskipun seperti yang dikatakan ~ dukun, Anda perlu memperbarui setiap shell secara mandiri.
dmckee

Benar, Anda perlu melakukannya di setiap shell screen. AFAIK screentidak mengekspos soket atau serupa untuk berkomunikasi dengan sesi berjalan dari luar.
Benjamin Bannier

@ Dmckee tapi tentu saja setiap sesi baru screen sudah memiliki variabel lingkungan terbaru
Benjamin Bannier

Saya telah memutuskan untuk hanya menerima jawaban ini untuk saat ini. Jika saya pernah benar-benar menerapkan ini, saya akan memperbarui. Tetapi untuk saat ini, cukup hanya dengan memiliki perasaan fuzzy hangat mengetahui bahwa secara teori itu mungkin.
Ryan C. Thompson

2

Saya telah mengimplementasikan skrip untuk melakukan ini. Anda bisa mendapatkannya di sini: https://github.com/DarwinAwardWinner/screen-sendenv

Setelah menempatkan screen-sendenv.pyke dalam $PATH, Anda dapat menggunakan potongan berikut di .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
}

Untuk menggunakannya, jalankan saja screen_pushenvsebelum Anda menjalankan screen -runtuk memasang kembali ke sesi layar Anda. Kemudian, setelah melampirkan screen -r, Anda dapat memperbarui lingkungan di shell yang ada dengan screen_pullenv. Fungsi tmux melakukan hal yang sama untuk tmux, terminal multiplexer lain yang mirip dengan layar.


Wow Ryan, itu kode yang banyak. Apa yang salah dengan jawaban yang diterima sebelumnya (setidaknya itu menginspirasi)?
Benjamin Bannier

1
Yah, saya menemukan bahwa layar (dan juga tmux) memiliki perintah "setenv" yang menetapkan variabel lingkungan untuk layar itu sendiri, bukan shell di jendela layar saat ini. Jadi itu berarti bahwa setelah Anda menggunakan skrip saya, semua jendela yang baru dibuat di sesi layar itu akan secara otomatis mendapatkan lingkungan baru, tanpa harus menjalankan skrip pembaruan di setiap dari mereka. Tentu saja, skrip pembaruan masih bisa berguna untuk memperbarui shell yang ada, tetapi Anda harus menulis ulang untuk tidak membaca dari FIFO, tetapi untuk menanyakan sesi screen / tmux itu sendiri untuk nilai-nilai baru.
Ryan C. Thompson

Anda dapat melihat cara menarik variabel ke shell saat ini dari sesi layar / tmux di sini , di screen_updatedan tmux_updatefungsinya. Saya akan memperbarui jawaban saya dengan versi byobu-independen ini.
Ryan C. Thompson

1
Pokoknya, untuk langsung menjawab pertanyaan Anda tentang apa yang salah, jawaban Anda tidak cukup menjawab pertanyaan, melainkan menjawab pertanyaan terkait. Anda menunjukkan cara memperbarui variabel lingkungan di dalam shell yang berjalan di dalam sesi layar, tetapi tidak cara memperbarui variabel lingkungan di sesi layar itu sendiri (sedemikian rupa sehingga windows yang baru lahir mewarisi nilai-nilai baru). Saya menerimanya pada saat itu karena itu masih merupakan solusi yang baik, tetapi saya selalu berniat untuk akhirnya mengimplementasikan jawaban nyata atas pertanyaan saya sebagaimana ditanyakan . Jadi, tidak ada masalah pribadi.
Ryan C. Thompson

Hai Ryan, terima kasih sudah menjawab. Sekarang Anda menyebutkan setenvsaya melihat bagaimana ini lebih baik. Tidak jelas dari kode yang Anda tautkan. Terima kasih lagi!
Benjamin Bannier

2

Anda dapat memanggil setenvperintah untuk mengubah variabel lingkungan dalam proses layar secara interaktif, dengan menggunakan: Ctrl- A+ :setenv(Catat :karakter untuk memasukkan perintah layar.) Anda akan diminta untuk nama dan nilai variabel lingkungan.

Perhatikan bahwa (sesuai jawaban / komentar lain) ini memengaruhi proses layar (induk) dan karenanya sesi layar yang baru dibuat, tetapi bukan sesi layar Anda saat ini atau sesi layar yang ada.

Anda dapat menentukan nama dan nilai variabel lingkungan pada saat yang sama jika Anda ingin: Ctrl- A+ :setenv DISPLAY :100. Akan mengatur DISPLAY ke ": 100" untuk sesi layar baru.

Untuk menghapus variabel lingkungan, Anda dapat menggunakan 'unsetenv' - misalnya Ctrl- A+:unsetenv DISPLAY


0

Ini mungkin solusi yang lebih sederhana (Anda putuskan). Bagian penting adalah alias yang memanggil savedisplayfungsi setiap kali screenperintah dijalankan. Perintah-perintah tidak dijalankan secara otomatis, karenanya dapat dimasukkan ~/.bashrcsebagai ganti sesuatu yang sangat khusus seperti ~/.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'
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.