Як мені змусити "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. Як корінь, створіть python2симпосилання в / usr / bin /. Я шукаю рішення, яке б цього не вимагало. Це було очевидним варіантом на початку, але я хотів би рішення, яке міняє хост-систему якомога менше. Ось чому я хотів створити тимчасове посилання в поточній робочій директорії, додати CWD (тобто .) до мого шляху, а потім знищити це, коли закінчиться (тобто symlink).

  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. BTW, ваша проблема "python2" вирішена зараз, оскільки git-multimail приймає і python2, і python3 :-).
Матьє Мой

Розширене питання все ще не містить важливої ​​деталі: Як виглядає лінія shebang у виконуваних сценаріях? Бо git-multimail.pyце #!/usr/bin/env python2так, тож існує (відносно) простий спосіб зробити це.
alexis

Коментар @ 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).


Зрештою я здався. У коді занадто багато місць, які передбачають "python2", і не кожне локалізоване рішення охоплює всі можливості. Це найбільш підходящий кувалд для цього цвяха.
Евери Чан

@Avery, ти спробував моє рішення? Чи була проблема? Це не вимагало б вам додати python2до /usr/bin(хоча я розглядаю додавання його як поліпшення, якщо чесно).
alexis

Це може бути можливо з псевдонімом (...) Це неможливо, оскільки псевдонім впливає лише на командний рядок, а не на сценарії. Див. Як змінити стандартну версію Python в Debian 7.5?
Пьотр Доброгост

Це не правильна відповідь, принаймні це не вирішує питання, яке спонукало плаката задати питання.
smaudet

16

Я вважаю, ви працюєте над системою 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" в лінгво stackexchange ...


Під час запуску /usr/bin/pythonвін знаходить і виконує python2.7 в тому самому каталозі. Це дуже заплутане твердження. Якщо ви описуєте випадок, коли /usr/bin/pythonє символьне посилання, то будь ласка, будьте більш конкретні.
Пьотр Доброгост

це просто дивовижно погано ..
nicolas

Що дивно погано?
alexis

Так, явно тут не згадується те, що я думаю, що / usr / bin / python насправді не python, він просто шукає встановлений на MacOS python (python2.7, який посилається на папку frameworks). Я підозрюю, що @nicolas говорить, що фальшива версія пітону дивовижно погана - це зовсім хакер, і я б хотів, щоб Apple цього не зробила. ... Є багато речей, які я хотів би, щоб Apple не робила цього, а просто працювала над системою Unix.
smaudet

3

Спробуйте:

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

1
Не знаю, чому ви отримуєте знищення, це єдине рішення, яке працювало на мене
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
    

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. Це жахлива ідея.


Чому .в моєму $ PATH погана ідея? Якщо я покладу це в кінці, то останнє місце, яке буде шукано, - це моя поточна робоча директорія (тобто `PATH =" $ {PATH}: $ {PWD} ". Сценарій обгортки означає, що для кожного файлу python я доведеться створити додатковий файл. Посилання на обгортку до виконуваного файлу python просто створює для мене одне
Avery Chan

@AveryChan Я так не думаю. Скрипт обгортки може створювати функцію оболонки або псевдонім, який має те саме ім'я, що і виконуваний файл. Він також може --bind mountвиконуватись у поточному каталозі або (лише в Linux, я думаю) навіть chrootза необхідності. Але. в $PATHроботах для будь-якої директорії і не є специфічним. Це небезпечно для ваших користувачів. У будь-якому випадку, я дуже чітко продемонстрував, як це робити вище. Чи не відповідає вашим вимогам?
mikeserv

0

Відповідь @alexis, версія python в /usr/binне є справжнім python.

Це повинно бути очевидним трьома способами:

  1. Помилка, яку ми отримуємо, - це не та, яку пітон створює. Поведінка python - це не пошук іншого python, його виконання скриптів python.

  2. Якщо ви обчислите шазум /usr/bin/pythonі власне python2.7, який запускається:

shasum /usr/bin/python
3782d9ab14b35037c9c7fb665439a5fa695c54a6  /usr/bin/python
shasum /usr/bin/python2.7
476fa96c80ac26a85b2d3b01ddfd19e513660c2c  /usr/bin/python2.7

Вони абсолютно різні. Крім того, розміри файлів відрізняються на ~ 20 К байт:

ll /usr/bin/python
-rwxr-xr-x  1 root  wheel  66880 May 17  2019 /usr/bin/python

vs.

ll /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
-rwxr-xr-x  1 root  wheel  43104 May 17  2019 /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
  1. Нарешті, ви можете декомпілювати python2.7 та python та дослідити символи. Це трохи поза сферою просто "як символізувати python2.7 до python2 на osx".

Отже (як вказує на помилку) /usr/bin/pythonобертається і шукає /usr/bin/python2.7:

ll /usr/bin/python2.7
lrwxr-xr-x  1 root  wheel  75 Jul  1  2019 /usr/bin/python2.7 -> ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7

Ось чому наступні роботи (чемність @ відповідь liangmin-li):

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

Ласкаво просимо на сайт. Ви можете додати пояснення щодо того, як побачити з вашої вибірки вибірку, lsщо /usr/bin/python"не справжній пітон".
AdminBee

Це трохи зрозуміло, але я можу оновити, як ми можемо це визначити.
smaudet

Це може бути для того, хто знає розмір типового pythonбінарного перекладача, але пам’ятайте, що відповіді тут повинні бути використані для більш загальної аудиторії U&L ...
AdminBee

1
Я оновив зразок. Доведення бінарної ідентичності є складною проблемою, тому я не цілком вирішую, що тут (розміри можуть бути законно різними між версіями, поведінка може змінюватися - докази, які я розміщував у своїй оновленій відповіді, полягає в тому, як поводиться ця система проти того, як Встановлення ванільного пітону повинно вести себе. Я не думаю, що відповідь про зворотну інженерію бінарний пітон тут буде доречним або дуже корисним). Але я зрозумів вашу думку.
smaudet
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.