Как мне получить 'realpath', чтобы найти мою символическую ссылку?

13

Я использую MacOSX в bashкачестве оболочки. У меня есть символическая ссылка, созданная так:

ln -s /usr/bin/python python2 

У меня есть пакет, который использует python2, и я хочу создать символьную ссылку в моем текущем рабочем каталоге, к /usr/bin/pythonкоторому фактически относится python2. Когда я делаю python2из командной строки, я получаю эту ошибку:

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

Но вызов его таким образом ./python2разрешает путь правильно. Мой PATHимеет .в этом. На самом деле я изменил его, для тестирования, чтобы иметь только .в нем.

Как мне решить это? Благодарность!


контекст

Ряд предложенных ниже решений не подойдет для меня. Я старался изобразить свой вопрос как можно более сфокусированным и кратким, чтобы люди не утонули в море текста, но, очевидно, мне нужно предоставить больше информации.

Я пытаюсь сделать разработку на пакете, который я клонировал из git. Оригинальный пакет git-multimail, был / был разработан для некоторого варианта Linux (я полагаю, Ubuntu). Я пытался изменить его, чтобы иметь возможность использовать его и его набор тестов на MacOSX с минимальными изменениями, насколько это возможно. Вот почему некоторые из предложенных решений не идеальны:

  1. В качестве пользователя root создайте python2символическую ссылку в / usr / bin /. Я ищу решение, которое бы не требовало этого. Вначале это был очевидный вариант, но я бы хотел, чтобы решение, которое как можно меньше модифицировало хост-систему. Вот почему я хотел создать временную символическую ссылку в текущем рабочем каталоге, добавить CWD (т.е. .) к моему пути, а затем уничтожить его, когда закончите (т.е. символическую ссылку).

  2. Создайте скрипт-обертку для вызова скрипта python с существующим python. Проблема с этим заключается в том, что большая часть тестового набора использует фактические файлы script_files в качестве исполняемых файлов, в зависимости от shebang, чтобы найти правильную среду выполнения. Это значило бы значительно изменить набор тестов. В этом контексте (фрагмент кода тестовой структуры см. Ниже) мне пришлось бы добавить оболочку для каждого .pyфайла; кроме того, пользователь / разработчик должен знать о различных правилах использования пакета в зависимости от того, в какой системе он работает (т.е. в MacOSX убедитесь, что вы не используете файлы python, не вызывая их через оболочку или явно вызывая /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. Меняются все python2ссылки на python. README предлагает это, но фактически делает управление версиями бесполезным, поскольку система видит изменение как новую версию, хотя на самом деле это не так (семантически).

Я использовал (3), но я пытаюсь найти лучшее решение. Я согласен с тем, что так обстоят дела (то есть нет подходящего способа указать 'python2' на /usr/bin/pythonто, что он переносимый и ненавязчивый, без большого количества изменений в наборе тестов и реальной платформе).

Эйвери Чан
источник
1
Привет! Простоln -s /usr/bin/python /usr/bin/python2
enedil
На самом деле я разрабатываю git-multimail на Linux. Но я бы хотел, чтобы патчи и тестеры работали на OS X. Кстати, ваша проблема с «python2» теперь решена, так как git-multimail принимает и python2, и python3 :-).
Матье Мой
В расширенном вопросе все еще отсутствует важная деталь: как выглядит строка shebang в исполняемых скриптах? Поскольку git-multimail.pyэто #!/usr/bin/env python2так, есть (относительно) простой способ сделать это.
Алексис
@ комментарий enedil не сделал работу, однако ln -s /usr/bin/python2.7 /usr/local/bin/python2сделал
Phylliida

Ответы:

3

Если вам нужно разрешить (или исследовать) символическую ссылку, вы можете использовать независимую от платформы библиотеку bash 'realpath-lib'. По умолчанию он эмулирует readlink и будет работать на Mac или Unix. Его можно найти на Github или Bitbucket, и это бесплатно.

Но, похоже, вы хотите просто сделать python2 (а не ./python2) из ​​своего локального (рабочего) каталога. Возможно, это можно сделать с помощью псевдонима в вашем .bashrc, иначе вам нужно будет добавить рабочий каталог (содержащий символическую ссылку) в переменную среды PATH. Это также можно сделать только для текущего сеанса или в файле .bashrc для будущих сеансов. Это может быть решением для конкретного пользователя.

Другим вариантом, который будет работать для всех пользователей, будет создание символической ссылки python2 на / usr / bin / python в другом каталоге пути, например, в / usr / local / bin. Возможно что-то вроде:

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

Тогда любой пользователь или скрипт должен найти команды python или python2. Конечно, эта опция требует прав администратора (root) для установки.

AsymLabs
источник
Я в конце концов сдался. В коде слишком много мест, где предполагается использование «python2», и не каждое локализованное решение охватывает все возможности. Это самый подходящий кувалда для этого гвоздя.
Эйвери Чан
@ Эйвери, ты попробовал мое решение? Была ли проблема? Это не потребовало бы вам добавить python2к /usr/bin(хотя я рассматриваю добавление его как улучшение, если честно).
Алексис
Это можно сделать с помощью псевдонима (...) Это невозможно, поскольку псевдоним влияет только на командную строку, а не на сценарии. См. Как изменить версию Python по умолчанию в Debian 7.5?
Петр Доброгост
15

Я полагаю, что вы используете систему Apple для управления несколькими версиями одной и той же программы и переключения между ними. Вы можете выполнить то, что хотите, менее изящно, но без проблем, с помощью следующего сценария с именем python2:

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

Сделайте его исполняемым ( chmod +x python2), и вы в деле.

Объяснение проблемы:

При запуске /usr/bin/pythonон находит и выполняет python2.7 в том же каталоге. Ваша символическая ссылка не работает, потому что система переходит по символической ссылке /usr/bin, затем ищет и не может найти python2 там. Вы можете сделать еще один шаг, используя «жесткую ссылку» вместо символической ссылки:

rm python2
ln /usr/bin/python python2

Теперь нет символической ссылки для подражания, только два имени файла для одного и того же файла (inode). Но сейчас я терплю неудачу со следующим сообщением:

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

Обратите внимание python22.7: фреймворк добавляет 2.7к имени, которое вы создали! Вместо того, чтобы пытаться разобраться в этом и создать лес ссылок, который соответствует его ожиданиям, я рекомендую вам не вмешиваться в структуру управления версиями и использовать решение, предложенное выше.

PS. Возможно, было бы лучшее решение: если бы вы объяснили, что вам нужно сделать для начала (почему вы должны предоставить python2в качестве псевдонима python), кто-то, вероятно, может помочь вам сделать это по-другому. Это известно как «проблема XY» в lingo stackexchange ...

Alexis
источник
Когда вы запускаете /usr/bin/python, он находит и выполняет python2.7 в том же каталоге. Это очень запутанное утверждение. Если вы описываете случай, когда /usr/bin/pythonесть символическая ссылка, пожалуйста, будьте более конкретны.
Петр Доброгост
это просто удивительно плохо ..
Николас
Что удивительно плохого?
Алексис
2

Пытаться:

ln -s /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /usr/local/bin/python2
Лянмин Ли
источник
Не знаю, почему вы получаете отрицательные отзывы, это единственное решение, которое сработало для меня
xApple
1

Вы можете использовать команду Unix readlink чтобы узнать физический путь к ссылкам.

Примеры

Скажем, у меня есть следующая ссылка:

$ 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. Чтобы найти значение, на которое указывает символическая ссылка

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

    ПРИМЕЧАНИЕ: приведенный выше результат может быть другой ссылкой. Чтобы решить эту проблему см. № 2 ниже.

  2. Чтобы узнать абсолютный путь к значению, на которое указывает символическая ссылка

    $ readlink -f /usr/bin/etags
    /usr/bin/ctags
SLM
источник
0

Я не понимаю - как вы считаете, что ссылка на оболочку в порядке, но не сценарий оболочки? ? Любой из них является просто уровнем косвенности. И разве вам не придется инструктировать своих пользователей только вызывать его из определенного каталога?

В любом случае, вы можете получить текущий рабочий каталог в $PATH:

 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

Пожалуйста, получите. из вашего $PATH. Это ужасная идея.

mikeserv
источник
Почему .в моем $ PATH плохая идея? Если я поставлю его в конец, то последнее место, которое будет просмотрено, - это мой текущий рабочий каталог (то есть `PATH =" $ {PATH}: $ {PWD} ". Сценарий-обертка означает, что для каждого файла python Мне нужно создать дополнительный файл. Ссылка-обертка на исполняемый файл python просто создает для меня одну вещь
Avery Chan
@AveryChan Я так не думаю. Сценарий оболочки может быть источником функции оболочки или псевдонима с тем же именем, что и исполняемый файл. Он также может выполнять --bind mountисполняемый файл в текущем каталоге или (я думаю, только в linux) даже chrootпри необходимости. Но . в $PATHработах для любого каталога и не является конкретным. Это опасно для ваших пользователей. В любом случае я очень четко продемонстрировал, как это сделать выше. Разве это не соответствует вашим требованиям?
mikeserv