Como obtenho o 'realpath' para encontrar o meu link simbólico?

11

Estou no MacOSX usando bash como meu shell. Eu tenho link simbólico, criado assim:

ln -s /usr/bin/python python2 

Eu tenho um pacote que usa python2 e quero criar um link de símbolo no meu diretório de trabalho atual para /usr/bin/python , que é, na verdade, python2. Quando eu faço um python2 da linha de comando, recebo este erro:

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

Mas invocá-lo assim ./python2 resolve o caminho corretamente. Meu PATH tem . . Na verdade, eu modifiquei, para testar, só tenho . .

Como resolvo isso? Obrigado!

Contexto

Algumas das soluções sugeridas abaixo não funcionam para mim. Eu tentei destilar minha pergunta o mais focada e breve possível para que as pessoas não se afogassem em um mar de texto, mas claramente eu preciso fornecer mais informações.

Estou tentando desenvolver um pacote que eu clonei do git. O pacote original, git-multimail , é / foi desenvolvido em alguma variante do Linux (eu estou supondo que o Ubuntu). Estou tentando modificá-lo para poder usá-lo e a sua suíte de testes no MacOSX com a menor modificação possível. Veja por que algumas das soluções propostas não são ideais:

  1. Como root, crie um link simbólico python2 em / usr / bin /. Estou procurando uma solução que não exija isso. Esta foi uma opção óbvia no começo, mas gostaria de uma solução que modifique o sistema host o mínimo possível. É por isso que eu queria criar um link simbólico temporário no diretório de trabalho atual, adicionar o CWD (ou seja, . ) ao meu caminho e, em seguida, destruir isso quando terminar (ou seja, o link simbólico).

  2. Crie um script wrapper para chamar o script python com o python existente. O problema com isso é que grande parte do conjunto de testes usa os scripts_real como executáveis, dependendo do shebang para encontrar a execução correta. meio Ambiente. Isso significaria editar a suíte de testes consideravelmente. Neste contexto, (veja abaixo um trecho da estrutura de teste), eu teria que adicionar um wrapper para cada arquivo .py ; Além disso, o usuário / desenvolvedor teria que estar ciente das diferentes regras para usar o pacote, dependendo de qual sistema eles estão (ou seja, no MacOSX, certifique-se de não usar os arquivos python sem invocá-los via invólucro ou chamando explicitamente /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. Alterando todas as referências python2 para python . O README sugere isso, mas isso efetivamente torna o controle de versão inútil, já que o sistema vê a alteração como nova versão, quando na verdade é não (semanticamente).

Eu tenho usado (3), mas estou tentando encontrar uma solução melhor. Estou disposto a aceitar que é assim que as coisas são (ou seja, não há uma maneira adequada de apontar 'python2' para /usr/bin/python que seja portátil e discreto sem muitas mudanças no conjunto de testes e na estrutura real). / p>     

por Avery Chan 25.04.2014 / 20:50

5 respostas

2

Se você precisar resolver (ou investigar) um link simbólico, você pode usar a biblioteca bash independente de plataforma 'realpath-lib'. Por padrão, ele emula o readlink e funciona no Mac ou no Unix. Pode ser encontrado em Github ou Bitbucket e é grátis.

Mas parece que você quer apenas fazer o python2 (ao invés de ./python2) a partir do seu diretório local (funcionando). Pode ser possível fazer isso com um alias em seu .bashrc ou, caso contrário, você precisará adicionar o diretório de trabalho (que contém seu symlink) à sua variável de ambiente PATH. Isso também pode ser feito apenas para a sessão atual ou no arquivo .bashrc para sessões futuras. Isso pode ser uma solução para apenas um usuário específico.

Outra opção que funcionaria para todos os usuários seria criar o link simbólico python2 para / usr / bin / python em outro diretório no caminho, digamos em / usr / local / bin. Talvez algo como:

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

Então, qualquer usuário ou script deve encontrar os comandos python ou python2. Claro que esta opção requer privilégios de admin (root) para instalar.

    
por 25.04.2014 / 23:20
14

Acredito que você esteja entrando em conflito com o sistema da Apple para gerenciar e alternar entre várias versões do mesmo programa. Você pode realizar o que deseja, com menos elegância, mas sem problemas, com o seguinte script chamado python2 :

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

Torne-o executável ( chmod +x python2 ) e você está no negócio.

Explicação do problema:

Quando você executa /usr/bin/python , ele encontra e executa python2.7 no mesmo diretório. Seu link simbólico falha porque o sistema segue o symlink para /usr/bin , então procura e > não consegue encontrar python2 lá. Você pode dar um passo adiante usando um "link físico" em vez de um link simbólico:

rm python2
ln /usr/bin/python python2

Agora não há link simbólico a seguir, apenas dois nomes de arquivos para o mesmo arquivo (inode). Mas agora eu falho com a seguinte mensagem:

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

Observe o python22.7 : A estrutura está adicionando 2.7 ao nome que você criou! Em vez de tentar desvendar isso e configurar uma floresta de links que corresponda às suas expectativas, recomendo que você fique fora do caminho da estrutura de gerenciamento de versões e use a solução sugerida acima.

PS. Pode haver uma solução melhor: se você explicasse o que precisava fazer para começar (por que você precisa fornecer python2 como um alias para python ), alguém provavelmente pode ajudá-lo a fazer isso de uma maneira diferente. Isso é conhecido como "problema XY" no jargão do stackexchange ...

    
por 25.04.2014 / 23:48
1

Você pode usar o comando readlink do Unix para descobrir um caminho físico de links.

Exemplos

Digamos que eu tenha o seguinte 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. Para encontrar o valor que um link simbólico aponta para

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

    NOTA: O resultado acima pode ser outro link. Para resolver isso, veja o item 2 abaixo.

  2. Para descobrir o caminho absoluto do valor que um link simbólico aponta para

    $ readlink -f /usr/bin/etags
    /usr/bin/ctags
    
por 25.04.2014 / 21:41
0

Eu não entendo - como você acredita que um link é ok, mas não um script ? Qualquer um é apenas nível de indireção. E você ainda não teria que instruir seus usuários apenas para chamá-lo de um determinado diretório?

Em qualquer caso, você pode obter o diretório de trabalho atual em $PATH , é claro:

 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

Por favor, consiga. fora do seu $PATH . Essa é uma ideia horrível.

    
por 28.04.2014 / 05:59
-1

Tente:

ln -s /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /usr/local/bin/python2
    
por 18.03.2016 / 03:29