Ekran GNU nie odziedziczy mojej ŚCIEŻKI po 10.5.8

11

Codziennie używam ekranu do moich potrzeb terminalowych i jestem z tego całkiem zadowolony. Ostatnio jednak, zrobiłem kilka nowości do moich plików konfiguracyjnych bash i zauważyłem, że zachodziło różne PATHelementy ( PATH, MANPATH, INFOPATH, etc) w 2 miejscach. Zmodyfikowałem pliki, aby były takie, jakie powinny być, a teraz wszystkie moje zmienne środowiskowe są ustawione raz .bash_profile. Na tym polega mój problem.

Najwyraźniej ustawiłem je w dwóch miejscach z powodu ekranu. Pojawi się ekran tylko wykonać .bashrci czy nie wydaje się, aby odziedziczyć moje PATHlub innym środowisku zmiennych poprawnie z mojej oryginalnej powłoki bash. Ponieważ to tylko wykonuje, .bashrca teraz ustawiam tylko moje zmienne .bash_profile, otrzymuję niekompletne PATH.

Moje pytanie brzmi zatem, jak przenieść moje zmienne środowiskowe na ekran bez powielania. Czytanie Bashdokumentów wydaje się wskazywać, że może to być rodzaj powłoki używanej przez ekran do logowania, tj. Interaktywna powłoka bez logowania, ale nie mogłem wymyślić, jak zmusić ekran do korzystania z określonego rodzaju powłoki, tylko powłoka do użycia przez -s /bin/bash.

Możesz przeglądać moje pliki konfiguracyjne na mojej stronie GitHub . To jest zatwierdzenie, które zepsuło ekran .

EDYCJA: Używam Screen version 4.00.03 (FAU) 23-Oct-06i zwykle wywołuję toscreen -h 50000

EDYCJA: Byłem w stanie przetestować to na Cygwin ( CYGWIN_NT-5.1 1.7.1(0.218/5/3) i686, Screen version 4.00.03 (FAU) 23-Oct-06) i wykazuje inne zachowanie niż na moim Macu.

Specyficzne zachowanie, które teraz odkryłem, polega na tym, że w Cygwin zmiany, które wprowadzam PATHw .bash_profile, są powielane po wejściu na screen, a następnie kolejne tworzenie okien ekranowych nie powielają ścieżki, ale ponownie źródłują .bash_profile.

Aby zilustrować zachowanie, o którym mówię:

Wyjście z nowego terminala:

...

PATH: /home/tvishe01/bin/emacs/bin:/home/tvishe01/bin:/usr/local/bin:/usr/bin:/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/Program Files/ATI Technologies/ATI.ACE/Core-Static:/groovy-1.6.1/bin:/usr/lib/lapack

MANPATH: /home/tvishe01/share/man:/usr/local/man:/usr/share/man:/usr/man::/usr/ssl/man

Aliases:
alias ..='cd ..'
alias ...='cd ../..'

...

[~]$

Wynik pierwszego wywołania screena:

[~]$ screen -h 50000 -s -/bin/bash

...

PATH: /home/tvishe01/bin/emacs/bin:/home/tvishe01/bin:/usr/local/bin:/usr/bin:/bin:/home/tvishe01/bin/emacs/bin:/home/tvishe01/bin:/usr/local/bin:/usr/bin:/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/Program Files/ATI Technologies/ATI.ACE/Core-Static:/groovy-1.6.1/bin:/usr/lib/lapack

MANPATH: /home/tvishe01/share/man:/usr/local/man:/usr/share/man:/usr/man:/home/tvishe01/share/man:/usr/local/man:/usr/share/man:/usr/man::/usr/ssl/man:/usr/ssl/man

Aliases:
alias ..='cd ..'
alias ...='cd ../..'

...

[~]$

Kolejne połączenia z C-a c:

...

PATH: /home/tvishe01/bin/emacs/bin:/home/tvishe01/bin:/usr/local/bin:/usr/bin:/bin:/home/tvishe01/bin/emacs/bin:/home/tvishe01/bin:/usr/local/bin:/usr/bin:/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/Program Files/ATI Technologies/ATI.ACE/Core-Static:/groovy-1.6.1/bin:/usr/lib/lapack

MANPATH: /home/tvishe01/share/man:/usr/local/man:/usr/share/man:/usr/man:/home/tvishe01/share/man:/usr/local/man:/usr/share/man:/usr/man::/usr/ssl/man:/usr/ssl/man

Aliases:
alias ..='cd ..'
alias ...='cd ../..'

...

[~]$

Możesz zobaczyć

Tim Visher
źródło
Duplikacja jest spowodowana tym, że bash został skonfigurowany tak, aby bezwarunkowo dodawać te wpisy za pomocą powłoki „login”, a ekran wyświetla polecenie, aby wywołać bash jako powłokę „login”. Przepisałem swoją odpowiedź, aby spróbować rozwiązać ogólne problemy dotyczące powłok, ekranu i zmiennych środowiskowych.
Chris Johnsen

Odpowiedzi:

16

zmienne ekranowe i środowiskowe

Domyślnie screen przekazuje swoje powłoki (i inne procesy) niezależnie od zmiennych środowiskowych, które miał w momencie rozpoczęcia sesji (tj. Ponowne połączenie nie zmienia zmiennych środowiskowych, które są podawane nowym powłokom). Ponieważ jednak zarówno pliki konfiguracyjne ekranu, jak i powłok często zmieniają zmienne środowiskowe, istnieje wiele miejsc, w których można wprowadzić nieoczekiwane zmiany. Istnieje kilka zmiennych, takich jak TERM , które ekran prawie zawsze się zmienia, ale są one generalnie wymagane dla funkcji, które zapewnia screen .

Powiedzmy, że ani konfiguracja twojej powłoki, ani konfiguracja ekranu nie zmodyfikuje zmiennej o nazwie FOOBAR (całkiem prawdopodobne, w sumie). Jeśli rozpoczniesz sesję FOOBAR=foo screen, wszystkie powłoki utworzone w tej sesji będą miały zmienną środowiskową o nazwie FOOBAR o wartości foo.

Sprawy stają się bardziej skomplikowane w przypadku zmiennych, które albo screen albo twoja powłoka mogą modyfikować.

Brakujące ustawienia podczas korzystania z ekranu

Powłoki logowania

Jeśli okaże się, że brakuje niektórych ustawień w powłokach uruchamianych za pomocą ekranu , przyczyną może być to, że powłoka jest skonfigurowana tylko do aktualizacji tych ustawień dla powłok „logujących się”. Większość muszle zrozumieć specjalną konwencję (C: **argv == '-'), że ekran może być skonfigurowany do użycia.

Według dokumentacji ekranu :

polecenie powłoki

Ustaw polecenie, które ma zostać użyte do utworzenia nowej powłoki. Zastępuje to wartość zmiennej środowiskowej $ SHELL. Jest to przydatne, jeśli chcesz uruchomić wzmacniacz tty, który oczekuje na uruchomienie programu określonego w $ SHELL. Jeśli polecenie zaczyna się znakiem „-”, powłoka zostanie uruchomiona jako powłoka logowania.

Aby mieć powłoki startowe ekranu jako powłoki logowania, uruchom ekran za pomocą screen -s -/bin/bashlub dodaj tę linię do .screenrc:

shell -/bin/bash

Dostosuj ścieżkę do dowolnej powłoki, której używasz.

Konfiguracja ekranu

Brakujące lub resetowane zmienne środowiskowe mogą być również spowodowane poleceniami setenvi unsetenvpoleceniami w pliku konfiguracyjnym ekranu . Trzeba będzie sprawdzić zarówno .screenrc w swoim katalogu domowym i dowolnie plik Twoja kompilacja ekranu używa jako „screenrc system” (można spróbować polecenia jak strings "$(which screen)" | fgrep -i screenrcznaleźć ścieżkę, która została skonfigurowana w czasie kompilacji, jest to zwykle / etc / screenrc dla ekranu instalowanego przez system ; instalacje dodatków prawdopodobnie użyją innej nazwy ścieżki). Możesz użyć, SCREENRC=/dev/null SYSSCREENRC=/dev/null screenaby tymczasowo uniknąć tych plików ustawień, ale istnieje opcja czasu kompilacji, która uniemożliwia skuteczne użycie SYSSCREENRC (przypuszczalnie po to, aby administratorzy systemu mogli wymusić trochę wstępnej konfiguracji).

Powiel ustawienia podczas korzystania z ekranu

Dość powszechne jest dodawanie elementów do zmiennej środowiskowej, takiej jak PATH, w plikach konfiguracyjnych powłoki, aby zaktualizowana wartość była dostępna dla normalnych sesji powłoki (np. Xterm lub innych okien terminali, sesji konsoli itp.). Jeśli takie elementy zostaną dodane w konfiguracji powłoki na powłokę (lub, jeśli używasz -/path/to/shellustawienia opisanego powyżej, w konfiguracji logowania na powłoki), wówczas powłoka uruchomiona przez screen prawdopodobnie będzie miała wiele kopii dodanych elementów.

Jedną ze strategii, aby tego uniknąć, jest umieszczenie wszystkich dodatków do zmiennych, takich jak PATH, w konfiguracji logowania dla powłoki i unikanie używania -/path/to/shellustawień powłoki z ekranem .

Inną strategią jest tylko warunkowo dodawanie nowych elementów do zmiennej. Zależnie od powłoki, kod do wykonania tego może być nieco skomplikowany, ale zwykle może być enkapsulowany w funkcji powłoki dla łatwego użycia.

Jeszcze inną strategią jest zawsze zaczynać od stałej wartości w plikach konfiguracyjnych. Może to czasami powodować problemy podczas przenoszenia plików konfiguracyjnych z systemu do systemu, gdy wartości domyślne mogą się znacznie różnić.

Diagnostyka

Jeśli nie możesz bezpośrednio zauważyć, gdzie następuje konkretna modyfikacja, możesz wypróbować następujące czynności, aby wyśledzić, gdzie następuje zmiana.

Sprawdź bieżącą wartość w początkowej powłoce:

echo "$PATH"

Sprawdź, jak sama powłoka modyfikuje wartość podczas tworzenia podpowłoki:

/bin/bash -c 'echo "$PATH"'

Sprawdź, jak powłoka modyfikuje wartość, gdy tworzona jest podpowłoka „login”:

perl -e '$s=shift;exec {$s} "-$s", @ARGV or die "unable to start shell"' /bin/bash
echo "$PATH"
exit

Sprawdź, jak screen modyfikuje wartość:

printf '#!/bin/sh\nl=/tmp/echo-var.log;rm -f "$l"; echo $PATH >"$l"' >/tmp/echo-var &&
chmod a+x /tmp/echo-var &&
screen -s /tmp/echo-var &&
cat /tmp/echo-var.log
Chris Johnsen
źródło
To rozwiązuje część mojego problemu. Niestety nie idzie to w pełni. Teraz ekran działa dobrze, screen -s -/bin/bashale nie zachowuje się, ponieważ spodziewałem się, że będzie działał pod Cygwin na mojej maszynie roboczej . Na tej maszynie uruchamiam screen -h 50000i po prostu dziedziczy mój PATHplik bez ponownego pobierania pliku. Działa to zarówno za każdym razem, gdy uruchamiam nowe okno.
Tim Visher
Środowisko procesu tworzenia ekranu powinno zawsze być dziedziczone przez wszystkie jego elementy potomne (z wyjątkiem rzeczy takich jak TERM, które mogą zastąpić). Spróbuj FOOBAR=baz screensprawdzić echo $FOOBARw oknach powłoki od screeni screen -s -/bin/bash. Obie odmiany powinny mieć FOOBAR= baz. Jeśli twój PATHjest modyfikowany, będziesz musiał wyśledzić, co to robi. Spróbuj SYSSCREENRC=/dev/null SCREENRC=/dev/null screen, jeśli to pozwoli ci PATHprzejść, prawdopodobnie jest to setenv PATHw /etc/screenrclub ~/.screenrc. W przeciwnym razie .bashrcrobisz to.
Chris Johnsen
Dokonałem dużego przepisania / dodania do mojej odpowiedzi.
Chris Johnsen
2

Ostatnim razem, gdy zobaczyłem podobny problem, rozwiązałem go, używając screen -lekranu startowego.

Możesz użyć tej -lopcji podczas wywoływania screen(włącz tryb logowania ; kontrolowany również przez polecenia deflogini loginw .screenrc), aby ustawić, czy screen ma domyślnie logować okno (dodawanie / usuwanie wpisu / etc / utmp).

Tryb logowania jest domyślnie włączony, ale można go zmienić podczas kompilacji. Jeśli screen nie jest skompilowany z obsługą utmp, te polecenia nie są dostępne.

Wydaje mi się, że nie potrzebuję -ltrybu na domyślnym ekranie Debiana Lenny'ego (v4.0.3); wydaje się być domyślnie włączony. Mój ~/.profilei ~/.bashrcsą poprawnie czytane. Jak się przywołujesz screen? Jakiej wersji używasz?

quack quixote
źródło
Zgodnie z tą teorią, niescreen -ln powinienem uruchamiać mojej , a ona wciąż działa. więc spróbuj flagi, ale to prawdopodobnie nie jest właściwa odpowiedź. na razie zostawię to tutaj. ~/.profile-l
szarlatan
Wygląda na to, że -lkontroluje tylko to, czy screendodaje pozycję do utmppliku, a nie to, czy wywołuje nowe powłoki z własną -lopcją, czy używa -niestandardowej opcji exec-with- prefix.
Chris Johnsen
2

Problem leży w zachowaniu uruchomionym na Leopardzie. Zobacz ten raport o błędach MacPorts na ekranie Leoparda, aby zobaczyć, dlaczego nie zostanie naprawiony, dopóki nie uda ci się w jakiś sposób cofnąć uruchomionej wersji Snow Leoparda.

https://trac.macports.org/ticket/18235#comment:26

ClashTheBunny
źródło
1

Nie ma nic złego w pozyskiwaniu .bashrc z .bash_profile. Jeśli używasz swojego komputera tylko lokalnie, twój .bash_profile będzie w większości przypadków pozyskiwany tylko podczas pierwszego logowania (oczywiście są inne czasy, gdy jest on pozyskiwany).

Organizuję pliki tak, że jeśli chcę coś zrobić tylko podczas logowania, umieszczam informacje w pliku .bash_profile, a dla wszystkich innych - w pliku .bashrc. ŚCIEŻKA to jedna rzecz, którą umieściłem w moim .bashrc, a ja pozyskuję .bashrc w moim .bash_profile.


źródło
Czy zechciałbyś opublikować gdzieś swoje pliki .bashrci .bash_profilepliki, bym mógł je zobaczyć? Problem, na który natknąłem się podczas robienia czegoś podobnego, polegał na tym, PATHże narastałam za każdym razem, gdy tworzyłem nową instancję ekranu, ponieważ odziedziczyłaby starą, PATHa następnie ponownie dodała wszystko.
Tim Visher
Przepraszam Tim, nie widziałem tego ... Zmieniłem wiele rzeczy dookoła, aby nie miały większego sensu, ale w zasadzie to robię. # .bash_profile if [-f ~ / .bashrc]; następnie . ~ / .bashrc fi Następnie umieszczam wszystko inne w .bashrc, z wyjątkiem rzeczy, które chcę rozpocząć przy pierwszym logowaniu, które również przechodzą w .bash_profile. ŚCIEŻKA jest obsługiwana w .bashrc jako seria linii zamiast jednej definicji ścieżki, tak jak większość eksportuje ŚCIEŻKA = / ścieżka / do / binariów1: $ ŚCIEŻKA eksportu ŚCIEŻKA = / ścieżka / do / binariów2: $ ŚCIEŻKA
0

Kiedy mam jakiś problem, że jak utworzyć plik $HOME/.debugi wszystkie pliki pozyskiwane / wykonywany podczas logowania / shell wywołania (np ~/.bashrc, ~/.bash_profile, ~/.profile, /etc/bashrc, etc) Mam w pierwszej linii

test -f $HOME/.debug && echo $HOME/.bashrc 1>&2

lub podobne. Do konkretnego debugowania możesz także dodać takie rzeczy jak

test -f $HOME/.debug && echo PATH now equals $PATH 1>&2

W ten sposób możesz być w 100% absolutnie pewien, jakie pliki są lub nie są używane.

Przekierowanie do stderr jest ważne, w wielu sytuacjach nie chcesz, aby coś popsuło standardowe wyjście.

hlovdal
źródło
0

Możesz pozostać przy .profile, ponieważ system nie dotyka bashrc (jak sesja graficzna) Teraz masz po prostu dwa różne zestawy środowisk - jeden z .profile, a drugi dla bash z .bashrc.

ZaB
źródło