Jaki jest najlepszy sposób dystrybucji zmiennych / niezależny od powłoki, aby ustawić zmienne środowiskowe?

31

Pytanie mówi wszystko. Obecnie używam Arch Linux i zsh, ale chciałbym rozwiązania, które (przynajmniej) działa zarówno na VT, jak i xterms, a także (mam nadzieję, że najlepiej) będzie nadal działać, jeśli zmienię dystrybucje lub powłoki.

Słyszałem bardzo różne odpowiedzi na to pytanie w dokumentach różnych dystrybucji. Ubuntu mówi „użyj .pam_environment”. Myślę, że w Arch to, co zalecają, zależy od twojej powłoki. Obecnie umieszczam wszystko w .profile, a jeśli powłoka z jakiegoś powodu nie pobiera tego źródła (np. Bash, jeśli istnieje .bash_profile), zastępuję to, ręcznie go zdobywając. Ale wygląda na to, że musi być lepszy sposób.

strugee
źródło
2
Nie ma to nic wspólnego z dystrybucją, a wszystko z powłoką. Nie jestem jednak pewien, czy jest to przenośny sposób.
Joseph R.
Hmm Niesamowite .
strugee

Odpowiedzi:

29

Niestety nie ma w pełni przenośnej lokalizacji do ustawiania zmiennych środowiskowych. Dwa najbliższe pliki ~/.profileto tradycyjna lokalizacja i działa od razu po wyjęciu z pudełka wielu konfiguracji, a ~/.pam_environmenttakże nowoczesna, powszechna, ale ograniczona alternatywa.

Co włożyć ~/.pam_environment

Plik ~/.pam_environmentjest odczytywany przez wszystkie metody logowania, które używają PAM i które mają włączony ten plik. Dotyczy to obecnie większości systemów Linux.

Główną zaletą ~/.pam_environmentjest to, że (po włączeniu) jest odczytywany przed uruchomieniem powłoki użytkownika, więc działa niezależnie od typu sesji, powłoki logowania i innych złożoności. Działa nawet w przypadku nieinteraktywnych loginów, takich jak su -c somecommandi ssh somecommand.

Głównym ograniczeniem ~/.pam_environmentjest to, że możesz umieszczać tam tylko proste zadania, a nie złożoną składnię powłoki. Składnia tego pliku jest następująca.

  • Pliki są analizowane linia po linii.
  • Wiodące białe znaki są ignorowane.
  • Opcjonalnie możesz rozpocząć linie od exporti pojedynczą spacją (nie tabulatorem, idź do rysunku).
  • Następnie każda linia musi mieć formę, w VAR=VALUEktórej VAR składa się z liter, cyfr i znaków podkreślenia.
  • # rozpoczyna komentarz, nie może pojawić się w wartości.
  • Jeśli WARTOŚĆ zaczyna się od 'lub "zawiera inny identyczny cytat, wówczas VAR jest ustawiany na ciąg znaków między cytatami (wszystko po drugim cytacie jest ignorowane). W przeciwnym razie VAR jest ustawiany na ciąg znaków po =znaku.
  • Jeśli nie =, zmienna jest usuwana ze środowiska.

Z drugiej strony ~/.pam_environmentdziała w różnych okolicznościach. Z drugiej strony, nie można mieć żadnych ustawień dynamicznych, takich jak oparcie wartości zmiennej na innej zmiennej (np. Dodanie katalogu do PATH) lub użycie wyniku polecenia (np. Sprawdzenie, czy katalog lub program jest obecny), a niektóre Znaki ( #'", nowa linia) są niemożliwe lub kłopotliwe do wprowadzenia wartości.

Co włożyć ~/.profile

Ten plik powinien mieć przenośną składnię sh (POSIX). Używaj tylko rozszerzeń ksh lub bash (tablic [[ … ]]itp.), Jeśli wiesz, że twój system ma takie powłoki jako /bin/sh.

Ten plik może być odczytywany przez skrypty w automatycznych aplikacjach, więc nie powinien wywoływać programów, które generują dane wyjściowe lub wywołania exec. Jeśli chcesz to zrobić przy logowaniu w trybie tekstowym, zrób to tylko dla interaktywnych powłok. Przykład:

case $- in *i*)
  # Display a message if I have new mail
  if mail -e; then echo 'You have new mail'; fi
  # If zsh is available, and this looks like a text-mode login, run zsh
  case "`ps $PPID` " in
    *" login "*)
      if type zsh >/dev/null 2>/dev/null; then exec zsh; fi;;
  esac
esac

Jest to przykład użycia /bin/shjako powłoki logowania i przejścia do ulubionej powłoki. Zobacz także, w jaki sposób mogę użyć bash jako powłoki logowania, gdy mój administrator nie chce mi go zmienić

Kiedy ~/.profilenie jest odczytywany przy graficznym logowaniu?

Różne powłoki logowania odczytują różne pliki.

Jeśli twoja powłoka logowania jest bash

Bash czyta ~/.bash_loginlub ~/.bash_profilejeśli istnieją zamiast ~/.profile. Również bash nie czyta ~/.bashrcw powłoce logowania, nawet jeśli jest interaktywny. Aby nigdy więcej nie pamiętać tych dziwactw, utwórz ~/.bash_profilez następującymi dwoma wierszami:

. ~/.profile
case $- in *i*) . ~/.bashrc;; esac

Zobacz także Których plików instalacyjnych należy użyć do konfigurowania zmiennych środowiskowych za pomocą bash?

Jeśli twoją powłoką logowania jest zsh

Zsh czyta ~/.zprofilei ~/.zlogin, ale nie ~/.profile. Zsh ma inną składnię niż sh, ale może czytać ~/.profilew trybie emulacji sh. Możesz użyć tego do ~/.zprofile:

emulate sh -c '. ~/.profile'

Zobacz także Zsh nie uderza w ~ / .profile

Jeśli twoja powłoka logowania jest inną powłoką

Nie możesz wiele zdziałać - wystarczy użyć /bin/shpowłoki logowania, a ulubionej powłoki (np. Ryby) jako powłoki interaktywnej. Tak właśnie robię z Zsh. Zobacz wyżej przykład wywoływania innej powłoki z ~/.profile.

Zdalne polecenia

Podczas wywoływania polecenia zdalnego bez przechodzenia przez interaktywną powłokę nie wszystkie powłoki odczytują plik startowy.

Ksh czyta plik określony przez ENVzmienną, jeśli uda ci się go przekazać.

Bash czyta, ~/.bashrcjeśli nie jest interaktywny (!), A jego proces nadrzędny jest wywoływany rshdlub sshd. Więc można rozpocząć ~/.bashrcz

if [[ $- != *i* ]]; then
  . ~/.profile
  return
fi

Zsh zawsze czyta, ~/.zshenvkiedy się zaczyna. Używaj ostrożnie, ponieważ jest to odczytywane przez każdą pojedynczą instancję zsh, nawet jeśli jest to podpowłoka, w której ustawiono inne zmienne. Jeśli zsh jest twoją powłoką logowania i chcesz jej używać do ustawiania zmiennych tylko dla poleceń zdalnych, użyj osłony: ustaw jakąś zmienną ~/.profile, na przykład MY_ENVIRONMENT_HAS_BEEN_SET=yesi sprawdź tę osłonę przed odczytaniem ~/.profile.

if [[ -z $MY_ENVIRONMENT_HAS_BEEN_SET ]]; then emulate sh -c '~/.profile'; fi

Przypadek logowania graficznego

Wiele dystrybucji, menedżerów wyświetlania i środowisk pulpitu jest uruchamianych ~/.profileprzez jawne pozyskiwanie ich ze skryptów startowych lub uruchamianie powłoki logowania.

Niestety, nie ma ogólnej metody obsługi kombinacji distro / DM / DE, gdzie ~/.profilenie jest czytany.

Jeśli korzystasz z tradycyjnej sesji rozpoczętej przez ~/.xsession, jest to miejsce, w którym powinieneś ustawić swoje zmienne środowiskowe; zrób to przez pozyskiwanie ~/.profile(tj . ~/.profile.). Zauważ, że w niektórych konfiguracjach skrypty startowe środowiska pulpitu będą się ~/.profileponownie pobierać.

Gilles „SO- przestań być zły”
źródło
Co ma case $- in *i*)zrobić?
qodeninja
2
@qodeninja Wykonuje następujące instrukcje (aż do dopasowania ;;lub esac), jeśli $-pasuje do wzorca *i*, tj. jeśli $-zawiera i, tj. jeśli powłoka jest interaktywna.
Gilles „SO- przestań być zły”
$-jest ciągiem aktualnie ustawionych opcji powłoki. (jak set -x). ioznacza interaktywną powłokę.
Peter Cordes,
Nie możesz po prostu zdobyć wspólnego pliku, powiedzmy ~/.config/env, nawet bez emulacji?
Kevin Suttle
1
@ StéphaneChazelas To purystyczny pogląd. Zachowuję .profilezgodność z dość starymi pociskami Bourne'a, ale zdaję sobie sprawę, że niektórym ludziom to po prostu nie obchodzi. Nie mam nic przeciwko ludziom, którzy zakładają, że sh = bash dla własnych plików, dbam tylko o to, czy opublikują #!/bin/shskrypt korzystający z funkcji bash.
Gilles 'SO - przestań być zły'
4

O ile mi wiadomo, nie ma żadnego standardu agnostycznego dla dystrybucji i powłoki, jak ustawić zmienne środowiskowe.

Najczęstszym i de facto standardem wydaje się być /etc/profilei ~/.profile. Drugim najczęściej występującym wydaje się być /etc/environmenti ~/.pam_environment.

Wydaje mi się, że cała dokumentacja, którą znalazłem, już znalazłem. Wymieniam je tutaj dla pozostałych czytelników.

  • Debian zaleca /etc/profilei ~/.profile( link ).
  • Ubuntu zaleca /etc/environmenti ~/.pam_environment( link ).
  • Arch Linux wspomina m.in. /etc/profilei /etc/environment( link ).

Bonus: tekst kwestionujący użycie i / lub niewłaściwe użycie /etc/environmentw Debianie ( link , ostatnia aktualizacja 2008).

lesmana
źródło
Niezależnie od używanego pliku nadal wpadniesz na niezgodną składnię między różnymi powłokami.
Joseph R.
1
@JosephR. czy większość powłok nie zachowuje kompatybilności wstecznej sh? Dopóki trzymasz się POSIX, myślałbym, że nic ci nie będzie ...
evilsoup
1
AFAIK, w którym nie można przypisywać zmiennych cshi znajomych w sposób POSIX (potrzebujesz czegoś takiego jak setlub setenv)
Joseph R.
0

Dodałem następujący skrypt ~ / bin / agnostic_setenv:

#!/bin/csh -f
set args = ($*)
if ($#args == 1) then
   echo "export $args[1]="
   exit 0
endif

if ($#args == 2) then
   if ("$args[1]" =~ *csh*) then 
      echo "setenv $args[2]"
      exit 0
   else
      echo "export $args[1]=$args[2]"
      exit 0
   endif
endif

echo "setenv $args[2] $args[3]"

A w ~ / .perl-homedir używam:

eval `${HOME}/bin/agnostic_setenv $shell PERL_HOMEDIR 0`

Podobny skrypt dla agnostic_unsetenv:

#!/bin/csh -f
set args = ($*)
if ($#args == 1) then
   echo "export $args[1]"
   exit 0
endif

echo "unsetenv $args[2]"
exit 0
Kobi
źródło