risposta-alla-domanda-sullo-sviluppo-web-bd.com

Come aggiungere correttamente un percorso a PATH?

Mi chiedo dove debba essere aggiunto un nuovo percorso alla variabile d'ambiente PATH. So che questo può essere realizzato modificando .bashrc (ad esempio), ma non è chiaro come farlo.

Per di qua:

export PATH=~/opt/bin:$PATH

o questo?

export PATH=$PATH:~/opt/bin
994
Paolo

Le cose semplici

PATH=$PATH:~/opt/bin

o

PATH=~/opt/bin:$PATH

a seconda che tu voglia aggiungere ~/opt/bin alla fine (da cercare dopo tutte le altre directory, nel caso in cui vi sia un programma con lo stesso nome in più directory) o all'inizio (da cercare prima di tutte le altre directory).

È possibile aggiungere più voci contemporaneamente. PATH=$PATH:~/opt/bin:~/opt/node/bin o variazioni sull'ordinazione funzionano bene. Non inserire export all'inizio della riga poiché presenta ulteriori complicazioni (vedi sotto in "Note su shell diverse da bash").

Se PATH viene creato da molti componenti diversi, potresti finire con voci duplicate. Vedere Come aggiungere il percorso della home directory per essere scoperto da Unix quale comando? e Rimuovere le voci duplicate $ PATH con il comando awk per evitare di aggiungere duplicati o rimuoverli.

Alcune distribuzioni inseriscono automaticamente ~/bin nel tuo PERCORSO se esiste, comunque.

Dove metterlo

Inserisci la riga per modificare PATH in ~/.profile o in ~/.bash_profile se è quello che hai.

Nota che ~/.bash_rc non viene letto da nessun programma e ~/.bashrc è il file di configurazione delle istanze interattive di bash. Non è necessario definire le variabili di ambiente in ~/.bashrc. Il posto giusto per definire variabili d'ambiente come PATH è ~/.profile (o ~/.bash_profile se non ti interessano le shell diverse da bash). Vedi Qual è la differenza tra loro e quale dovrei usare?

Non inserirlo in /etc/environment o ~/.pam_environment: questi non sono file Shell, non puoi utilizzare sostituzioni come $PATH lì dentro. In questi file, puoi solo sovrascrivere una variabile, non aggiungerla ad essa.

Potenziali complicazioni in alcuni script di sistema

Non è necessario export se la variabile è già nell'ambiente: qualsiasi modifica del valore della variabile si riflette nell'ambiente.¹ PATH è praticamente sempre nell'ambiente; tutti i sistemi unix lo hanno impostato molto presto (di solito nel primo processo, in effetti).

Al momento dell'accesso, puoi fare affidamento sul fatto che PATH sia già nell'ambiente e che contenga già alcune directory di sistema. Se stai scrivendo uno script che potrebbe essere eseguito in anticipo durante l'impostazione di un qualche tipo di ambiente virtuale, potresti dover assicurarti che PATH non sia vuoto ed esportato: se PATH non è ancora impostato , quindi qualcosa come PATH=$PATH:/some/directory imposterà PATH su :/some/directory e il componente vuoto all'inizio indica la directory corrente (come .:/some/directory).

if [ -z "${PATH-}" ]; then export PATH=/usr/local/bin:/usr/bin:/bin; fi

Note su conchiglie diverse da bash

In bash, ksh e zsh, export è una sintassi speciale, ed entrambi PATH=~/opt/bin:$PATH e export PATH=~/opt/bin:$PATH fai anche la cosa giusta. In altre shell in stile Bourne/POSIX come dash (che è /bin/sh su molti sistemi), export viene analizzato come un normale comando, il che implica due differenze:

Quindi in gusci come trattino, export PATH=~/opt/bin:$PATH imposta PATH sulla stringa letterale ~/opt/bin/: seguito dal valore di PATH fino al primo spazio. PATH=~/opt/bin:$PATH (un compito semplice) non richiede virgolette e fa la cosa giusta. Se vuoi usare export in uno script portatile, devi scrivere export PATH="$HOME/opt/bin:$PATH", o PATH=~/opt/bin:$PATH; export PATH (o PATH=$HOME/opt/bin:$PATH; export PATH per portabilità anche su Bourne Shell che non ha accettato export var=value e non ha fatto l'espansione della tilde).

¹ Questo non era vero nelle shell Bourne (come nell'attuale Bourne Shell, non nelle moderne shell in stile POSIX), ma è molto improbabile che si incontrino conchiglie così vecchie in questi giorni.

Ad ogni modo funziona, ma non fanno la stessa cosa: gli elementi di PATH sono controllati da sinistra a destra. Nel tuo primo esempio, eseguibili in ~/opt/bin avrà la precedenza su quelle installate, ad esempio, in /usr/bin, che può essere o meno ciò che desideri.

In particolare, dal punto di vista della sicurezza, è pericoloso aggiungere percorsi in primo piano, perché se qualcuno può ottenere l'accesso in scrittura al tuo ~/opt/bin, possono inserire, ad esempio, un ls diverso, che probabilmente useresti invece di /bin/ls senza accorgersene. Ora immagina lo stesso per ssh o per il tuo browser o la tua scelta ... (Lo stesso vale tre volte per averlo inserito nel tuo percorso.)

88
Ulrich Schwarz

Sono confuso dalla domanda 2 (poiché rimosso dalla domanda poiché era dovuto a un problema non correlato):

Qual è un modo praticabile per aggiungere più percorsi su linee diverse? Inizialmente pensavo che questo potesse fare il trucco:

export PATH=$PATH:~/opt/bin
export PATH=$PATH:~/opt/node/bin

ma non perché il secondo compito non aggiunge solo ~/opt/node/bin, ma anche l'intero PATH precedentemente assegnato.

Questa è una possibile soluzione alternativa:

export PATH=$PATH:~/opt/bin:~/opt/node/bin

ma per leggibilità preferirei avere un compito per un percorso.

Se dici

PATH=~/opt/bin

questo è tutto che sarà nel tuo PERCORSO. PERCORSO è solo una variabile d'ambiente e se si desidera aggiungere al PERCORSO, è necessario ricostruire la variabile con esattamente il contenuto desiderato. Cioè, quello che dai come esempio alla domanda 2 è esattamente quello che vuoi fare, a meno che non mi manchi completamente il punto della domanda.

Uso entrambi i moduli nel mio codice. Ho un profilo generico che installo su ogni macchina su cui lavoro che assomiglia a questo, per adattarsi alle directory potenzialmente mancanti:

export PATH=/opt/bin:/usr/local/bin:/usr/contrib/bin:/bin:/usr/bin:/usr/sbin:/usr/bin/X11
# add optional items to the path
for bindir in $HOME/local/bin $HOME/bin; do
    if [ -d $bindir ]; then
        PATH=$PATH:${bindir}
    fi
done
39
Carl Cravens

Linux determina il percorso di ricerca eseguibile con $PATH variabile d'ambiente. Per aggiungere directory/data/myscripts all'inizio di $PATH variabile di ambiente, utilizzare quanto segue:

PATH=/data/myscripts:$PATH

Per aggiungere quella directory alla fine del percorso, utilizzare il seguente comando:

PATH=$PATH:/data/myscripts

Ma i precedenti non sono sufficienti perché quando si imposta una variabile di ambiente all'interno di uno script, tale modifica è effettiva solo all'interno dello script. Esistono solo due modi per aggirare questa limitazione:

  • Se all'interno dello script, si esporta la variabile d'ambiente, è efficace all'interno di tutti i programmi chiamati dallo script. Si noti che non è efficace all'interno del programma che ha chiamato lo script.
  • Se il programma che chiama lo script lo fa per inclusione invece di chiamare, qualsiasi modifica dell'ambiente nello script è efficace all'interno del programma chiamante. Tale inclusione può essere effettuata con il comando punto o il comando sorgente.

Esempi:

$HOME/myscript.sh
source $HOME/myscript.sh

Inclusione fondamentalmente incorpora lo script "chiamato" nello script "chiamante". È come un #include in C. Quindi è efficace all'interno dello script o del programma "chiamante". Ma, naturalmente, non è efficace in alcun programma o script chiamato dal programma chiamante. Per renderlo efficace lungo tutta la catena di chiamate, è necessario seguire l'impostazione della variabile di ambiente con un comando di esportazione.

Ad esempio, il programma Shell bash incorpora il contenuto del file .bash_profile per inclusione. Inserire le seguenti 2 righe in .bash_profile:

PATH=$PATH:/data/myscripts
export PATH

inserisce efficacemente quelle 2 righe di codice nel programma bash. Quindi all'interno di bash, la variabile $ PATH include $HOME/myscript.sh e, a causa dell'istruzione export, tutti i programmi chiamati da bash hanno l'alterato $PATH variabile. E poiché tutti i programmi eseguiti da un prompt di bash sono chiamati da bash, il nuovo percorso è in vigore per tutto ciò che si esegue dal prompt di bash.

La linea di fondo è che per aggiungere una nuova directory al percorso, è necessario aggiungere o anteporre la directory alla variabile di ambiente $ PATH all'interno di uno script incluso in Shell ed è necessario esportare $PATH variabile d'ambiente.

Ulteriori informazioni qui

25
Steve Brown

Da qualche tempo ho tenuto con me due funzioni pathadd e pathrm che aiutano ad aggiungere elementi al percorso senza la necessità di preoccuparsi delle duplicazioni.

pathadd accetta un argomento a percorso singolo e un argomento facoltativo after che, se fornito, verrà aggiunto a PATH altrimenti lo antepone.

In quasi tutte le situazioni, se stai aggiungendo al percorso, probabilmente vorrai sovrascrivere qualsiasi cosa già presente nel percorso, motivo per cui scelgo di anteporre per impostazione predefinita.

pathadd() {
    newelement=${1%/}
    if [ -d "$1" ] && ! echo $PATH | grep -E -q "(^|:)$newelement($|:)" ; then
        if [ "$2" = "after" ] ; then
            PATH="$PATH:$newelement"
        else
            PATH="$newelement:$PATH"
        fi
    fi
}

pathrm() {
    PATH="$(echo $PATH | sed -e "s;\(^\|:\)${1%/}\(:\|\$\);\1\2;g" -e 's;^:\|:$;;g' -e 's;::;:;g')"
}

Inseriscili in qualsiasi script che desideri modificare l'ambiente PATH e ora puoi farlo.

pathadd "/foo/bar"
pathadd "/baz/bat" after
export PATH

Sei sicuro di non aggiungere al percorso se è già lì. Se ora vuoi assicurarti /baz/bat è all'inizio.

pathrm "/baz/bat"
pathadd "/baz/bat"
export PATH

Ora qualsiasi percorso può essere spostato in primo piano se è già nel percorso senza raddoppiare.

20
Brett Ryan

Non posso parlare per altre distribuzioni, ma Ubuntu ha un file,/etc/environment, che è il percorso di ricerca predefinito per tutti gli utenti. Dal momento che il mio computer è utilizzato solo da me, ho inserito tutte le directory che desidero nel mio percorso lì, a meno che non sia un'aggiunta temporanea che ho inserito in uno script.

10
Jim Bradley

Ci sono alcune situazioni in cui utilizza PATH=/a/b:$PATH potrebbe essere considerato il modo "errato" di aggiungere un percorso a PATH:

  1. Aggiunta di un percorso che in realtà non è una directory.
  2. Aggiunta di un percorso che è già in PATH nella stessa forma.
  3. Aggiunta di un percorso relativo (poiché la directory effettiva cercata cambierebbe quando si cambia la directory di lavoro corrente).
  4. Aggiunta di un percorso che è già in PATH in una forma diversa (ovvero un alias dovuto all'utilizzo di symlink o ..).
  5. Se si evita di fare 4, non spostare il percorso in avanti di PATH quando si intende sovrascrivere altre voci in PATH.

Questa funzione (solo Bash) fa la "cosa giusta" nelle situazioni precedenti (con un'eccezione, vedi sotto), restituisce codici di errore e stampa messaggi Nice per gli umani. I codici di errore e i messaggi possono essere disabilitati quando non sono desiderati.

prepath() {
    local usage="\
Usage: prepath [-f] [-n] [-q] DIR
  -f Force dir to front of path even if already in path
  -n Nonexistent dirs do not return error status
  -q Quiet mode"

    local tofront=false errcode=1 qecho=echo
    while true; do case "$1" in
        -f)     tofront=true;       shift;;
        -n)     errcode=0;          shift;;
        -q)     qecho=':';          shift;;
        *)      break;;
    esac; done
    # Bad params always produce message and error code
    [[ -z $1 ]] && { echo 1>&2 "$usage"; return 1; }

    [[ -d $1 ]] || { $qecho 1>&2 "$1 is not a directory."; return $errcode; }
    dir="$(command cd "$1"; pwd -P)"
    if [[ :$PATH: =~ :$dir: ]]; then
        $tofront || { $qecho 1>&2 "$dir already in path."; return 0; }
        PATH="${PATH#$dir:}"        # remove if at start
        PATH="${PATH%:$dir}"        # remove if at end
        PATH="${PATH//:$dir:/:}"    # remove if in middle
    fi
    PATH="$dir:$PATH"
}

L'eccezione è che questa funzione non può canonicalizzare i percorsi aggiunti a PATH in altri modi, quindi se un alias non canonico per un percorso è in PATH, questo aggiungerà un duplicato. Cercare di canonicalizzare i percorsi già in PATH è una proposta rischiosa poiché un percorso relativo ha un significato ovvio quando viene passato a prepath ma quando già nel percorso non sai quale fosse l'attuale directory di lavoro quando è stato aggiunto.

7
cjs

Per aggiungere un nuovo percorso alla variabile d'ambiente PATH:

export PATH=$PATH:/new-path/

Per applicare questa modifica a ogni Shell che apri, aggiungila al file che Shell sorgente quando viene invocato. In diverse shell questo può essere:

  • Bash Shell: ~/.bash_profile, ~/.bashrc o profilo
  • Korn Shell: ~/.kshrc o .profile
  • Z Shell: ~/.zshrc o .zprofile

per esempio.

# export PATH=$PATH:/root/learning/bin/
# source ~/.bashrc
# echo $PATH

Puoi vedere il percorso fornito nell'output sopra.

7
Amit24x7

Per me (su Mac OS X 10.9.5), aggiungendo il nome del percorso (ad es. /mypathname) al file /etc/paths ha funzionato molto bene.

Prima di modificare, echo $PATH ritorna:

/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

Dopo aver modificato /etc/paths e riavviando Shell, la variabile $ PATH viene aggiunta con /pathname. Infatti, echo $PATH ritorna:

/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/mypathname

Quello che è successo è che /mypathname è stato aggiunto al $PATH variabile.

6
faelx

Ecco la mia soluzione:

PATH=$(echo -n $PATH | awk -v RS=: -v ORS=: '!x[$0]++' | sed "s/\(.*\).\{1\}/\1/")

Una fodera semplice e piacevole che non lascia un trascinamento :

5
AJ.