Come posso ottenere "realpath" per trovare il mio link simbolico?


13

Sono su MacOSX usando bashcome shell. Ho un collegamento simbolico, creato in questo modo:

ln -s /usr/bin/python python2 

Ho un pacchetto che usa python2 e voglio creare un collegamento simbolico nella mia directory di lavoro corrente a /usr/bin/pythoncui in realtà è python2. Quando faccio un python2dalla riga di comando ottengo questo errore:

python2: realpath couldn't resolve "/usr/bin/python2"

Ma invocarlo in questo modo ./python2risolve il percorso correttamente. Il mio PATHha .dentro. In effetti l'ho modificato, a scopo di test, per includerlo solo .in esso.

Come lo risolvo? Grazie!


Contesto

Alcune delle soluzioni suggerite di seguito non funzioneranno per me. Ho cercato di distillare la mia domanda nel modo più mirato e breve possibile in modo che le persone non affogassero in un mare di testo, ma chiaramente ho bisogno di fornire più informazioni.

Sto cercando di sviluppare su un pacchetto che ho clonato da Git. Il pacchetto originale git-multimail, è / è stato sviluppato su alcune varianti di Linux (suppongo Ubuntu). Ho provato a modificarlo per poterlo utilizzare e la sua suite di test su MacOSX con il minor numero di modifiche possibile. Ecco perché alcune delle soluzioni proposte non sono l'ideale:

  1. Come root, crea un python2link simbolico in / usr / bin /. Sto cercando una soluzione che non richiederebbe questo. Questa era un'opzione ovvia all'inizio, ma vorrei una soluzione che modifica il sistema host il meno possibile. Questo è il motivo per cui volevo creare un collegamento simbolico temporaneo nella directory di lavoro corrente, aggiungere il CWD (ovvero .) al mio percorso e quindi distruggerlo al termine (ovvero il collegamento simbolico).

  2. Crea uno script wrapper per chiamare lo script Python con il Python esistente. Il problema è che gran parte della suite di test utilizza gli script_file effettivi come file eseguibili, a seconda di shebang per trovare l'ambiente di esecuzione corretto. Ciò significherebbe modificare considerevolmente la suite di test. In questo contesto, (vedi sotto per uno snippet del framework di test), dovrei aggiungere un wrapper per ogni .pyfile; inoltre l'utente / sviluppatore dovrebbe essere a conoscenza delle diverse regole per l'utilizzo del pacchetto in base al sistema su cui si trovano (ovvero su MacOSX assicurarsi di non utilizzare i file Python senza invocarli tramite il wrapper o chiamare esplicitamente /usr/bin/python file.py).

    #! /bin/sh
    
    D=$(cd $(dirname "$0") && pwd)
    MULTIMAIL="$D/../git-multimail/git_multimail.py"
    POST_RECEIVE="$D/../git-multimail/post-receive"
    
    TESTREPO=$("$D/create-test-repo")
    
    HOME="$D"
    XDG_CONFIG_HOME="$D"
    GIT_CONFIG_NOSYSTEM=1
    export HOME XDG_CONFIG_HOME GIT_CONFIG_NOSYSTEM
    
    cd $TESTREPO
    
    test_email() {
        REFNAME="$1"
        OLDREV="$2"
        NEWREV="$3"
        echo "$OLDREV" "$NEWREV" "$REFNAME" | USER=pushuser "$MULTIMAIL"
    
    } 
  3. Modifica di tutti i python2riferimenti in python. Il README lo suggerisce, ma ciò rende effettivamente inutile il controllo della versione poiché il sistema vede il cambiamento come nuova versione, quando in realtà non lo è (semanticamente).

Sto usando (3) ma sto cercando di trovare una soluzione migliore. Sono disposto ad accettare che le cose vanno esattamente così (cioè non esiste un modo adatto per indicare 'python2' /usr/bin/pythonche sia portatile e discreto senza molte modifiche alla suite di test e al framework reale).


1
Hey! Justln -s /usr/bin/python /usr/bin/python2
enedil,

In effetti sviluppo git-multimail su Linux. Ma darei il benvenuto a patch e tester per farlo funzionare su OS X. A proposito, il tuo problema "python2" è stato risolto ora, poiché git-multimail accetta sia python2 che python3 :-).
Matthieu Moy,

Alla domanda estesa manca ancora un dettaglio cruciale: come appare la linea shebang negli script eseguibili? Perché git-multimail.pylo è #!/usr/bin/env python2, quindi c'è un modo (relativamente) semplice per farlo.
alexis,

Il commento di @ enedil non ha funzionato, tuttavia ln -s /usr/bin/python2.7 /usr/local/bin/python2ha funzionato
Phylliida,

Risposte:


3

Se hai bisogno di risolvere (o investigare) un collegamento simbolico puoi usare la libreria bash indipendente dalla piattaforma 'realpath-lib'. Di default emula il readlink e funzionerà su Mac o Unix. Può essere trovato su Github o Bitbucket ed è gratuito.

Ma sembra che tu voglia semplicemente fare python2 (piuttosto che ./python2) dalla tua directory locale (funzionante). Potrebbe essere possibile farlo con un alias nel tuo .bashrc o altrimenti dovrai aggiungere la directory di lavoro (che contiene il tuo link simbolico) alla variabile di ambiente PATH. Questo può essere fatto anche solo per la sessione corrente o all'interno del file .bashrc per le sessioni future. Questa potrebbe essere una soluzione solo per un utente specifico.

Un'altra opzione che funzionerebbe per tutti gli utenti sarebbe quella di creare il collegamento simbolico python2 a / usr / bin / python in un'altra directory sul percorso, diciamo in / usr / local / bin. Forse qualcosa del tipo:

sudo ln -s /usr/bin/python /usr/local/bin/python2

Quindi qualsiasi utente o script dovrebbe trovare i comandi python o python2. Naturalmente questa opzione richiede l'installazione dei privilegi di amministratore (root).


Alla fine ho rinunciato. Ci sono troppi posti che assumono 'python2' nel codice e non tutte le soluzioni localizzate coprono tutte le possibilità. Questa è la mazza più adatta per questo chiodo.
Avery Chan,

@Tutto, hai provato la mia soluzione? C'è stato un problema? Non ti avrebbe richiesto di aggiungere python2al /usr/bin(anche se visualizzare materiale aggiungerlo come un miglioramento, ad essere onesti).
alexis,

Potrebbe essere possibile farlo con un alias (...) Non è possibile poiché l'alias influenza solo la riga di comando e non gli script. Vedi Come modificare la versione predefinita di Python in Debian 7.5?
Piotr Dobrogost,

15

Credo che tu stia eseguendo il sistema Apple per la gestione e il passaggio tra più versioni dello stesso programma. Puoi realizzare ciò che vuoi, in modo meno elegante ma senza problemi, con il seguente script chiamato python2:

#!/bin/bash
exec /usr/bin/python "$@"

Rendilo eseguibile ( chmod +x python2) e sei in affari.

Spiegazione del problema:

Quando esegui /usr/bin/python, trova ed esegue python2.7 nella stessa directory. Il tuo collegamento simbolico fallisce perché il sistema segue il collegamento simbolico a /usr/bin, quindi cerca e non riesce a trovarlo python2 . Puoi fare un ulteriore passo in avanti usando un "hard link" invece di un link simbolico:

rm python2
ln /usr/bin/python python2

Ora non c'è nessun link simbolico da seguire, solo due nomi di file per lo stesso file (inode). Ma ora non riesco con il seguente messaggio:

python2: posix_spawn: /Users/alexis/.../python22.7: No such file or directory

Nota python22.7: il framework si sta aggiungendo 2.7al nome che hai creato! Invece di provare a svelare questo e impostare una foresta di collegamenti che corrisponda alle sue aspettative, ti consiglio di non intralciare il framework di gestione delle versioni e di utilizzare la soluzione suggerita sopra.

PS. Potrebbe esserci una soluzione migliore: se per prima cosa spiegassi cosa dovevi fare (perché devi fornire python2come alias python), qualcuno probabilmente può aiutarti a farlo in un modo diverso. Questo è noto come "problema XY" nel linguaggio stackexchange ...


Quando viene eseguito /usr/bin/python, trova ed esegue python2.7 nella stessa directory. Questa è un'affermazione molto confusa. Se descrivi il caso in cui si /usr/bin/pythontrova un collegamento simbolico, ti preghiamo di essere più specifico.
Piotr Dobrogost,

è semplicemente incredibilmente male ..
nicolas

Cosa è incredibilmente male?
alexis

2

Provare:

ln -s /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /usr/local/bin/python2

Non so perché stai ricevendo
voti negativi

1

È possibile utilizzare il comando Unix readlinkper scoprire un percorso fisico dei collegamenti.

Esempi

Di 'che ho il seguente link:

$ ls -l /usr/bin/etags
lrwxrwxrwx. 1 root root 29 Dec 10 22:56 /usr/bin/etags -> /etc/alternatives/emacs.etags

$ ls -l /etc/alternatives/emacs.etags
lrwxrwxrwx. 1 root root 20 Dec 10 22:56 /etc/alternatives/emacs.etags -> /usr/bin/etags.ctags

$ ls -l /usr/bin/etags.ctags
lrwxrwxrwx. 1 root root 5 Dec 10 22:56 /usr/bin/etags.ctags -> ctags

  1. Per trovare il valore a cui punta un collegamento simbolico

    $ readlink /usr/bin/etags
    /etc/alternatives/emacs.etags

    NOTA: il risultato sopra può essere un altro collegamento. Per risolvere il problema, vedere il n. 2 di seguito.

  2. Per scoprire il percorso assoluto del valore a cui punta un collegamento simbolico

    $ readlink -f /usr/bin/etags
    /usr/bin/ctags

0

Non capisco: come credi che un link wrapper sia ok, ma non uno script wrapper ? Uno dei due è semplicemente un livello di indiretta. E non dovresti comunque istruire i tuoi utenti a chiamarlo solo da una determinata directory?

In ogni caso, puoi $PATHovviamente ottenere l'attuale directory di lavoro :

 echo "echo \"Hi! I'm python\"" >|./python 
 chmod +x ./python 
 PATH="${PWD}:${PATH}" 
 python

 #OUTPUT#
 Hi! I'm python

 rm python 
 python -V 
 ln -s /usr/bin/python2 ./python 
 python -V

 #OUTPUT#
 Python 3.4.0
 Python 2.7.6

 PATH="${PATH#"${PWD}:"}" 
 python -V

 #OUTPUT#
 Python 3.4.0

Per favore, prendi. fuori dal tuo $PATH. È un'idea orribile.


Perché .nel mio $ PATH è una cattiva idea? Se lo metto alla fine, allora l'ultimo posto che verrà cercato è la mia directory di lavoro corrente (cioè `PATH =" $ {PATH}: $ {PWD} ". Uno script wrapper significa che per ogni file Python creare un file aggiuntivo. Un link wrapper all'eseguibile python crea solo una cosa per me da fare.
Avery Chan

@AveryChan Non penso proprio. Uno script wrapper può generare una funzione di shell o un alias con lo stesso nome dell'eseguibile. Può anche --bind mountl'eseguibile nella directory corrente o (solo Linux, immagino) anche chrootse necessario. Ma . in $PATHopere per qualsiasi directory e non è specifico. Questo è pericoloso per i tuoi utenti. In ogni caso, ho dimostrato molto chiaramente come farlo sopra. Non soddisfa i tuoi requisiti?
Mikeserv,
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.