Як мені змусити "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.