Impossibile generare correttamente .bashrc da uno script di shell


51

Normalmente possiamo sorgente ~/.bashrcfile usando questo comando

source ~/.bashrc

ma se lo scrivo in uno script di shell e lo eseguo, non succede nulla. Perché?
C'è un modo per fare questo?

La mia sceneggiatura:

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

Anche provato .(punto) invece di source. Stesso risultato

Risposte:


26

Uno script di shell viene eseguito nella sua istanza di shell. Tutte le impostazioni delle variabili, le definizioni delle funzioni e simili influenzano solo questa istanza (e forse i suoi figli) ma non la shell chiamante, quindi scompaiono al termine dello script.

Al contrario, il sourcecomando non avvia una nuova istanza della shell ma utilizza la shell corrente in modo che le modifiche rimangano.

Se vuoi che un collegamento legga il tuo .bashrc usa una funzione di shell o un alias invece di uno script di shell, come

alias brc='source ~/.bashrc'

Grazie per la tua rapida risposta La tua soluzione potrebbe funzionare, ma devo modificare manualmente il file bashrc per salvare la riga 'aliac brc = ....'. Sto cercando di sviluppare una GUI per cambiare la variabile d'ambiente. Quindi non posso modificare manualmente il file bashrc di un altro computer.
shantanu,

1
Devi correre source ~/.bashrcnella shell di cui vuoi cambiare l'ambiente. Non puoi cambiarlo da un altro processo. Forse (a livello globale) l'aggiunta di questo alias potrebbe far parte del processo di installazione della tua GUI.
Florian Diesch,

1
quindi inserisco il comando alias in precedenza nello script e quindi invoco brc quando voglio eseguire il sorgente del mio .bashrc o devo inserire quel comando alias in un file da qualche parte?
user137717

Quello che ho finito per fare è un'estensione della risposta di Florian Diesch. Potresti semplicemente usare un alias multilinea: alias brc = 'chmod a + x ~ / .bashrc; source ~ / .bashrc 'Sono ancora abbastanza nuovo, quindi non sono sicuro che questo sia considerato' cattiva pratica '. Funziona però.
A_user_appears

13

Di .bashrcsolito inizia:

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

Poiché il tuo script non ha PS1 impostato (perché non è interattivo), non ripristina il percorso perché esce presto. Per dimostrare, modifica il tuo script:

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

questo consentirà ora ai tuoi script di funzionare con il nuovo .bashrc. Nota: una volta terminato lo script, env verrà impostato su quello che era prima di iniziare lo script. Le modifiche verranno riflesse al successivo avvio di un terminale.


Almeno dal 16.04 e probabilmente prima, Ubuntu predefinito .bashrcutilizza un modo più affidabile per verificare che la shell sia interattiva. /etc/bash.bashrcha ancora il test PS1.
Zanna,

12

Provare:

exec bash

Questo dovrebbe ricaricare ~ / .bashrc, ~ / .bash_aliases, ecc.


9
Questo sostituisce l'attuale processo bash con uno nuovo. Non è molto più breve o più semplice dell'uso sourcema distrugge qualsiasi variabile e tale che l'utente ha impostato manualmente, il che può o meno ciò che desideri.
Florian Diesch,

resisti, nel contesto di uno script Shell con altri comandi dopo il sourcing di bashrc, metti i comandi che hanno bisogno del nuovo stato bash dopo quello exec bash, il modo in cui lo capisco comando dopo sarà ancora nelle stesse impostazioni bash di prima?
Tatsu

11

Voglio integrare la risposta di ravi :

Questo comportamento è specifico di Ubuntu (e probabilmente la maggior parte delle distro derivate), poiché il tuo ~/.bashrcfile predefinito inizia con un corto circuito, Ubuntu 18.04, ad esempio:

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

Ciò interromperà la valutazione del file se è in esecuzione in una shell non interattiva, come nel caso dello script poiché tutti gli script vengono eseguiti in una shell non interattiva e, successivamente, ogni file sourceerediterà questa proprietà.

eval mod

Ho scoperto un brutto trucco per aggirare Ubuntu in particolare, usando evalinvece di source:

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

Salta semplicemente le poche prime righe e valuta il resto, ~/.bashrcquindi il resto viene valutato e modifica l'esecuzione corrente.

Tieni presente che è un numero magico e potrebbe non funzionare tra le versioni di Ubuntu; ma può essere una buona soluzione se stai creando script per sistemi più o meno conosciuti.

Una soluzione più elaborata potrebbe comportare l'utilizzo di regex per indirizzare i bit specifici che interrompono la valutazione.

Alternativa Shebang

Un'altra alternativa che potrebbe funzionare meglio in alcuni scenari è forzare l'esecuzione dello script in una shell interattiva aggiungendo un flag nello shebang :

#!/bin/bash -i

Sii consapevole di alcune cose:

  • Si tratta di una pratica migliore per utilizzare la #!/usr/bin/env bashforma, ma in questo modo si non può avviare la shell con argomenti .
  • L'uso di -iha il proprio set di conseguenze, tra cui i programmi richiederanno l'interazione dell'utente e questo di solito non è destinato agli script, ad esempio l'installazione di debpacchetti potrebbe interrompere lo script quando dpkg configurerichiesto .
  • Inizialmente ho provato a utilizzare set -ie set +iad attivare e disattivare la funzionalità dove ne avevo bisogno, ma non funziona .

2

Nessuno degli altri metodi ha funzionato per me [ source /path/to/filevs . ./path/to/file, alias, ecc ...], fino a quando, grazie a questo tutorial, ho scoperto che usando:

#!/usr/bin/env bash faccenda

invece di quello più semplice, #!/usr/bin/envconsente agli argomenti di passare all'interprete, che credo sia la chiave qui - vedi questo documento per maggiori informazioni.

In ogni caso, se i comandi sorgente in qualsiasi forma non funzionano per te, prova a controllare il tuo shebang, questo potrebbe essere il problema :)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.