Nie można pomyślnie pobrać .bashrc ze skryptu powłoki

51

Zwykle możemy ~/.bashrcza pomocą tego polecenia pobrać plik źródłowy

source ~/.bashrc

ale jeśli napiszę to w skrypcie powłoki i wykonam, nic się nie stanie. Dlaczego?
Czy jest na to jakiś sposób?

Mój skrypt:

#!/bin/bash
chmod a+x ~/.bashrc
source ~/.bashrc

Próbowałem także .(kropka) zamiast source. Ten sam wynik.

shantanu
źródło

Odpowiedzi:

26

Skrypt powłoki jest uruchamiany we własnej instancji powłoki. Wszystkie ustawienia zmiennych, definicje funkcji itp. Wpływają tylko na to wystąpienie (i być może jego dzieci), ale nie na powłokę wywołującą, więc znikają po zakończeniu skryptu.

Natomiast sourcepolecenie nie uruchamia nowej instancji powłoki, ale używa bieżącej powłoki, więc zmiany pozostają.

Jeśli chcesz, aby skrót odczytał plik .bashrc, użyj funkcji powłoki lub aliasu zamiast skryptu powłoki, np.

alias brc='source ~/.bashrc'
Florian Diesch
źródło
Dziękuję za szybką odpowiedź. Twoje rozwiązanie może działać, ale muszę ręcznie edytować plik bashrc, aby zapisać wiersz „aliac brc = ....”. Próbuję opracować GUI do zmiany zmiennej środowiskowej. Nie mogę więc ręcznie edytować pliku bashrc innego komputera.
shantanu
1
Musisz uruchomić source ~/.bashrcw powłoce, którą chcesz zmienić środowisko. Nie możesz tego zmienić w innym procesie. Może (globalnie) dodanie tego aliasu może być częścią procesu instalacji GUI.
Florian Diesch,
1
więc czy umieściłem twoją komendę aliasu wcześniej w skrypcie, a następnie wywołałem brc, gdy chcę uzyskać źródło .bashrc lub muszę gdzieś umieścić komendę aliasu w pliku?
user137717,
To, co skończyłem, jest przedłużeniem odpowiedzi Floriana Diescha. Możesz po prostu użyć aliasu wieloliniowego: alias brc = 'chmod a + x ~ / .bashrc; source ~ / .bashrc 'Nadal jestem całkiem nowy, więc nie jestem pewien, czy uważa się to za „słabą praktykę”. Ale to działa.
A_user_appears pojawia się
13

Twój .bashrcrozpoczyna się zwykle:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

Ponieważ twój skrypt nie ma ustawionego PS1 (ponieważ nie jest interaktywny), nie resetuje ścieżki, ponieważ kończy się wcześnie. Aby zademonstrować, zmodyfikuj skrypt:

    #!/bin/bash
    chmod a+x ~/.bashrc
    PS1='$ '
    source ~/.bashrc

pozwoli to teraz twoim skryptom na pracę z nowym .bashrc. Uwaga: po zakończeniu skryptu env zostanie ustawione na to, co było przed uruchomieniem skryptu. Zmiany zostaną odzwierciedlone przy następnym uruchomieniu terminala.

Ravi Nankani
źródło
Przynajmniej od 16.04 i prawdopodobnie wcześniej, domyślne Ubuntu .bashrcużywa bardziej niezawodnego sposobu sprawdzenia, czy powłoka jest interaktywna. /etc/bash.bashrcwciąż ma test PS1.
Zanna,
12

Próbować:

exec bash

To powinno przeładować ~ / .bashrc, ~ / .bash_aliases itp.

Alin Andrei
źródło
9
Zastępuje to obecny proces bashowy nowym. Nie jest to dużo krótsze ani łatwiejsze niż używanie, sourceale niszczy wszelkie zmienne i takie, które użytkownik ustawił ręcznie - co może, ale nie musi, czego chcesz.
Florian Diesch,
trzymaj się, w kontekście skryptu Shell z innymi poleceniami po źródle bashrc, czy umieszczasz polecenia wymagające nowego stanu bash po tym exec bash, jak rozumiem to polecenie po będzie nadal w tych samych ustawieniach basha, co wcześniej?
tatsu
11

Chcę uzupełnić odpowiedź Raviego :

To zachowanie jest specyficzne dla Ubuntu (i prawdopodobnie większości pochodnych dystrybucji), ponieważ domyślny ~/.bashrcplik zaczyna się od zwarcia, Ubuntu 18.04, na przykład:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

Spowoduje to zatrzymanie oceny pliku, jeśli jest on uruchomiony w nieinteraktywnej powłoce, co ma miejsce w przypadku skryptu, ponieważ wszystkie skrypty są uruchamiane w nieinteraktywnej powłoce , a następnie każdy plik sourceodziedziczy tę właściwość.

eval włamać się

Dowiedziałem się brzydkiego włamania do obejścia Ubuntu, używając evalzamiast source:

eval "$(cat ~/.bashrc | tail -n +10)"

Po prostu pomija kilka pierwszych wierszy i ocenia resztę, ~/.bashrcwięc reszta jest oceniana i modyfikuje bieżące wykonanie.

Pamiętaj, że jest to magiczna liczba i może nie działać w różnych wersjach Ubuntu; ale może być dobrym rozwiązaniem, jeśli tworzysz skrypty dla mniej lub bardziej znanych systemów.

Bardziej wymyślne rozwiązanie może obejmować użycie wyrażenia regularnego do kierowania na określone bity, które zatrzymują ocenę.

Alternatywa Shebang

Inną alternatywą, która może działać lepiej w niektórych scenariuszach, jest zmuszanie skryptu do działania w interaktywnej powłoce poprzez dodanie flagi w shebang :

#!/bin/bash -i

Pamiętaj o kilku rzeczach:

  • Jest lepsza praktyka korzystania z #!/usr/bin/env bashformularza, ale ten sposób nie można uruchomić powłokę z argumentami .
  • Korzystanie z -ima swój własny zestaw konsekwencji, między innymi programy będą monitować o interakcję użytkownika i zwykle nie jest to przeznaczone dla skryptów, na przykład instalowanie debpakietów może zatrzymać skrypt po dpkg configurewyświetleniu monitu .
  • Początkowo próbowałem używać set -ii set +iwłączać i wyłączać tę funkcję tam, gdzie jej potrzebowałem, ale to nie działa .
stefanmaric
źródło
2

Żadna z pozostałych metod nie działała dla mnie [ source /path/to/filevs . ./path/to/file, alias itp.], Dopóki dzięki temu samouczkowi nie stwierdziłem, że przy użyciu:

#!/usr/bin/env bash szulernia

zamiast prostszego #!/usr/bin/envpozwala argumentom przekazać tłumacza, co myślę, że jest tutaj kluczem - zobacz ten dokument, aby uzyskać więcej informacji.

W każdym razie, jeśli polecenia źródłowe w jakiejkolwiek formie nie działają, spróbuj sprawdzić swój shebang, to może być problem :)

Nikksno
źródło