Kiedy `_` jest zmienną środowiskową powłoki bash?

10

Bash Manual mówi (manpage, mój nacisk):

Gdy Bash wywołuje polecenie zewnętrzne, zmienna $_jest ustawiana na pełną ścieżkę do polecenia i przekazywana do tego polecenia w jego środowisku.

I ( parametry specjalne ):

_

( $_podkreślenie.) Przy uruchamianiu powłoki ustaw bezwzględną nazwę ścieżki używaną do wywoływania powłoki lub skryptu powłoki wykonywanego tak, jak przekazano w środowisku lub liście argumentów. Następnie rozwija się do ostatniego argumentu do poprzedniego polecenia, po rozwinięciu. Ustawiono również na pełną ścieżkę używaną do wywołania każdego wykonanego polecenia i umieszczonego w środowisku wyeksportowanym do tego polecenia. Podczas sprawdzania poczty ten parametr przechowuje nazwę pliku poczty.

  1. W powłoce bash uruchamiam:

    $ bash
    $ export | grep '_=' 

    Zgodnie z instrukcją _powinna być zmienną środowiskową nowej powłoki bash. exportma wypisywać wszystkie zmienne środowiskowe nowej powłoki bash, ale nie wypisuje _. Zastanawiam się więc, czy _zmienna środowiskowa nowej powłoki bash?

  2. Tak naprawdę dzieje się w każdej powłoce bash

    $ export | grep '_='

    nic nie wydaje. Zastanawiam się więc, czy _kiedykolwiek jest zmienną środowiskową powłoki bash?

  3. Dla porownania:

    $ dash
    $ export  | grep '_='        
    export _='/bin/dash'

Mój post jest zainspirowany komentarzem Mike'a i odpowiedzią Stephane'a .

Tim
źródło
1
Jest to zmienna powłoki i jest przekazywana do środowiska polecenia ; niekoniecznie jest eksportowany do środowiska powłoki . exportjest wbudowany, ale jeśli go użyjesz printenv _, pokaże ci, jak został wywołany: /usr/bin/printenvw tym systemie.
Toby Speight
Zauważ, że bash -c export | grep _=(od bash), będzie pokazać jak skorupa rodzic powołuje się na bashkomendę, choć $_nie jest ustawiona na rodzica.
Toby Speight

Odpowiedzi:

13

Tak, _jest zmienną środowiskową nowej powłoki Bash; możesz to zobaczyć uruchamiając

tr '\0' '\n' < /proc/$$/environ | grep _=

wewnątrz powłoki: pokazuje zawartość początkowego środowiska powłoki. Nie zobaczysz go w pierwszej powłoce, ponieważ nie było poprzedniej powłoki, która mogłaby ją ustawić przed jej uruchomieniem.

Rozwijanie $_w Bash odnosi się do _specjalnego parametru, który rozwija się do ostatniego argumentu poprzedniego polecenia. (Wewnętrznie Bash obsługuje to za pomocą _zmiennej powłoki, która jest aktualizowana za każdym razem, gdy parsowana jest komenda, ale tak naprawdę jest to szczegół implementacji. Jest „nieportowany” za każdym razem, gdy parsowana komenda. ) exportNie wyświetla się, _ponieważ nie jest zmienna oznaczona jako wyeksportowana; możesz to jednak zobaczyć na wyjściu set.

W pierwszym przykładzie, nowe Analizuje powłoki bash i wykonuje polecenia w plikach startowych, więc gdy uruchomiony explore | grep '-=', _został już nadpisane i oznaczone jako nie eksport.

W tym dashprzykładzie wydaje się, że nie wykonuje on żadnego pliku startowego, więc widzisz zmienną jako zmienną środowiskową, która została ustawiona przez Bash przed uruchomieniem dash.

Stephen Kitt
źródło
Dzięki. Dlaczego w nowej powłoce bash nic nie export | grep '_='wyświetla? Dlaczego w oryginalnej powłoce bash nic nie tr '\0' '\n' < /proc/$$/environ | grep _=wyświetla?
Tim
9

exportbez argumentów wyświetla listę wszystkich eksportowanych zmiennych . _nie jest zmienną, ale jest wymieniony jako parametr specjalny .

Nieco mylące _byłoby również prawidłowe określenie zmiennej , w przeciwieństwie do nazw innych specjalnych parametrów. Przynajmniej Bash 4.4 pozwala na przypisanie do niego bez reklamacji. Jest to po prostu nieprzydatne, ponieważ efekt specjalny natychmiast zastępuje wartość.

ilkkachu
źródło
2
Baw się dobrze, próbując użyć _jako zmiennej ;-). Jest efektywnie tylko do zapisu, a wartość jest natychmiast tracona.
Stephen Kitt
1
Również wewnętrznie Bash traktuje _jak zmienną, dlatego pojawia się na wyjściu set. Jednak nie można go oznaczyć jako wyeksportowany, o ile mogę to ustalić.
Stephen Kitt
2
@StephenKitt, ale Bash 4.4 pozwala na oznaczenie go jako tylko do odczytu. Lub liczba całkowita. Z nieco zabawnymi wynikami.
ilkkachu
1
Ha, fajne znalezisko, to raczej zabawne!
Stephen Kitt,
5

Nie wszystkie zmienne powłoki są oznaczone jako wyeksportowane, jak widać na wyjściu declare -p.

bashOznaczanie $_jako eksportowane nie ma sensu, ponieważ automatycznie dodaje tę zmienną do środowiska procesów potomnych, ale z inną wartością niż ta, którą ma w powłoce (w tym momencie).

Wyświetlanie go jako wyeksportowanego po prostu wprowadzałoby użytkownika w błąd co do tego, co się stanie ze środowiskiem poleceń zewnętrznych.

Wszystkie „zmienne środowiska wykonawczego” BASH*nie są eksportowane.

Hauke ​​Laging
źródło