Jak ponownie załadować / etc / environment bez ponownego uruchamiania?

157

/etc/environmentjest oficjalnie poprawnym miejscem dla zmiennych systemowych dla całego systemu. Ale jak mogę ponownie załadować zadania w tym pliku bez ponownego uruchamiania lub ponownego logowania?

Co ciekawe, Google nie pomaga mi tutaj, oprócz dziesiątek postów na blogu sugerujących użycie

source /etc/environment

który oczywiście nigdy nie zadziała, ponieważ /etc/environmentjest to lista przypisań (po jednym w wierszu), a nie skrypt wykonywalny (stąd brakujące exportpolecenia w /etc/environment...).

fgysin
źródło
11
W całym systemie nie mam pojęcia. Do bieżącej sesji powłoki można użyć for line in $( cat /etc/environment ) ; do export $line ; done, jeśli format pliku to key=value.
Daniel Beck
2
Działa dla mnie bez export...
Izkata
2
@lzkata: Jeśli zmienna jest już wyeksportowana, nie trzeba jej eksportować ponownie ... Jeśli dodana zostanie nowa zmienna, która nie została jeszcze wyeksportowana, exportkonieczne byłoby ... (bez niej nie jest to zwykłe - zmienna środowiskowa w bieżącej powłoce, niedostępna w procesach potomnych)
Gert van den Berg
@DanielBeck dziękuję..plz dodaj komentarz jako odpowiedź!
Gadelkareem,
czy to działa również na Debianie i Centos?
Massimo,

Odpowiedzi:

122

Jedną z rzeczy, w których się mylisz, jest to, że /etc/environmentwymaga ponownego uruchomienia w celu ponownego załadowania. To jest niepoprawne. Plik jest odczytywany tylko przy logowaniu , gdy aktywowany jest stos PAM pam_env.so, a konkretnie ten , który czyta plik.

Wylogowywanie i z powrotem w to zastosować zmiany - aw rzeczywistości musi to zrobić, jeśli chcesz, aby wszystkie procesy otrzymywać nowe środowisko . Wszystkie inne „rozwiązania” 2 zastosują środowisko tylko do procesu pojedynczej powłoki, ale nie do niczego uruchamianego przez GUI, w tym nowych okien terminali. 1

Jeśli jednak nie masz nic przeciwko - brakowi exportkomend można zrekompensować za pomocą set -ai set +a. Nadal jednak jest to kiepski sposób, ponieważ plik nie używa również cytowania. Ale to powinno działać dobrze:

while read -r env; do export "$env"; done

1 Menedżer sesji GNOME umożliwia zmianę własnego środowiska, ale tylko w Initializationfazie:

$ gdbus call -e -d org.gnome.SessionManager \
                -o /org/gnome/SessionManager \
                -m org.gnome.SessionManager.Setenv \
                "FOO" "bar"
Error: GDBus.Error:org.gnome.SessionManager.NotInInitialization: Setenv
    interface is only available during the Initialization phase

2 gdb nie jest rozwiązaniem, ale czasem można go użyć. Musisz dołączyć go do uruchomionych procesów menedżera sesji (np. gnome-session), Menedżera okien (np. gnome-shellLub openbox), paska zadań / panelu, jeśli taki istnieje (np. xfce4-panel), I ogólnie wszystkiego innego, co mogłoby uruchamiać rzeczy. Dla każdego z tych procesów musisz dołączyć gdbdo niego za pomocą PID, wywołać putenv()funkcję za pomocą p, a następnie odłączyć za pomocą q:

$ sudo gdb -p $(pidof gnome-session)
GNU gdb (GDB) 7.7.1
[...]
Attaching to process 718
[...]
0x00007fc2cefed81d in poll () from /usr/lib/libc.so.6

(gdb) p putenv("FOO=bar")
$1 = 0

(gdb) p putenv("BAZ=qux")
$2 = 0

(gdb) q
A debugging session is active.
Quit anyway? (y or n) y
Detaching from program: /usr/bin/gnome-session, process 718

Zauważ, że debugger wstrzymuje proces, dlatego musisz łączyć się z menedżerami okien do komponowania tylko z innego tty (wirtualnej konsoli) lub przez SSH, w przeciwnym razie ekran zawiesiłby się.

Oprócz tego powinieneś zaktualizować środowisko używane przez dbus-daemon:

$ dbus-update-activation-environment --systemd FOO=bar BAZ=qux

W przypadku starszych systemów:

$ gdbus call -e -d org.freedesktop.DBus \
                -o /org/freedesktop/DBus \
                -m org.freedesktop.DBus.UpdateActivationEnvironment \
                "{'FOO': 'bar', 'BAZ': 'qux'}"
()
grawitacja
źródło
1
Właśnie przetestowałem podczas odczytu -r env; eksportuj „$ env”; zrobione na Ubuntu 16.04 i błędy. Czy chciałbyś więcej szczegółów?
Frank
while readMetoda odczytuje z stdin, więc prawdopodobnie chcesz coś do niej rury (np cat /etc/environment | while ...). Ale to nie będzie działać z cytatem sformatowanych plików środowiskowych ( key="value")
villasv
6

Nie jest to tak wyczerpujące, jak zaakceptowana odpowiedź, ale jeśli zacytowałeś zmienne w swoich /etc/environmentplikach, obie poprzednie metody (które w export $linejakiś sposób wykorzystują ) pójdą źle i skończysz na cytowanych wartościach.

  • Opcja 1: z tymczasowym plikiem źródłowym

sed 's/^/export /' /etc/environment > /tmp/env.sh && source /tmp/env.sh

  • Opcja 2: z wbudowanym for(dzięki @ Tim-Jones):

for env in $( cat /etc/environment ); do export $(echo $env | sed -e 's/"//g'); done

villasv
źródło
4
Krótszy: evalsed 's/^/export /' /etc/environment
Aaron McMillin
2
Wersja pliku innego niż tymczasowy:for env in $( cat /etc/environment ); do export $(echo $env | sed -e 's/"//g'); done
Tim Jones
7
Nawet krócej: set -a; source /etc/environment; set +a;.
ulidtko