ฉันจะได้รับ '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-multimailคือ / ได้รับการพัฒนาบน Linux บางรุ่น (ฉันคาดเดา Ubuntu) ฉันพยายามแก้ไขมันเพื่อให้สามารถใช้งานได้และชุดทดสอบใน MacOSX โดยมีการปรับเปลี่ยนน้อยที่สุด นี่คือสาเหตุที่โซลูชันที่เสนอบางรายการไม่เหมาะ:

  1. ในฐานะที่เป็น root ให้สร้างpython2symlink ใน / usr / bin / ฉันกำลังมองหาโซลูชันที่ไม่ต้องการสิ่งนี้ นี่เป็นตัวเลือกที่ชัดเจนในตอนแรก แต่ฉันต้องการโซลูชันที่ปรับเปลี่ยนระบบโฮสต์ให้น้อยที่สุด นี่คือเหตุผลที่ฉันต้องการสร้าง symlink ชั่วคราวในไดเรกทอรีการทำงานปัจจุบันเพิ่ม CWD (เช่น.) ไปยังเส้นทางของฉันแล้วทำลายสิ่งนี้เมื่อเสร็จสิ้น (เช่น symlink)

  2. สร้างสคริปต์ตัวตัดเพื่อเรียกสคริปต์ไพ ธ อนด้วยไพ ธ อนที่มีอยู่ ปัญหานี้คือชุดทดสอบส่วนใหญ่ใช้ script_files จริงเป็นไฟล์เรียกทำงานขึ้นอยู่กับ shebang เพื่อค้นหาสภาพแวดล้อมการเรียกใช้งานที่ถูกต้อง นี่จะหมายถึงการแก้ไขชุดทดสอบอย่างมาก ในบริบทนี้ (ดูตัวอย่างของกรอบการทดสอบด้านล่าง) ฉันจะต้องเพิ่ม wrapper สำหรับทุก.pyไฟล์ ผู้ใช้ / นักพัฒนาจะต้องตระหนักถึงกฎต่าง ๆ สำหรับการใช้แพคเกจขึ้นอยู่กับระบบที่พวกเขาอยู่บน (เช่นบน MacOSX ให้แน่ใจว่าคุณไม่ได้ใช้ไฟล์หลามโดยไม่ต้องเรียกพวกเขาผ่านเสื้อคลุมหรือโทรอย่างชัดเจน/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 pythonREADME แนะนำสิ่งนี้ แต่สิ่งนี้ทำให้การควบคุมเวอร์ชันไร้ประโยชน์เนื่องจากระบบมองว่าการเปลี่ยนแปลงนั้นเป็นเวอร์ชั่นใหม่เมื่อจริงแล้วมันไม่ใช่

ฉันใช้ (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 :-)
Matthieu Moy

คำถามที่ขยายออกยังขาดรายละเอียดที่สำคัญ: บรรทัด shebang ในสคริปต์ที่ปฏิบัติการได้มีลักษณะอย่างไร เพราะgit-multimail.pyมัน#!/usr/bin/env python2มีวิธีที่ค่อนข้างตรงไปตรงมาในการทำเช่นนี้
alexis

ความคิดเห็นของ @ enedil ไม่ทำงาน แต่ln -s /usr/bin/python2.7 /usr/local/bin/python2ได้
Phylliida

คำตอบ:


3

หากคุณต้องการแก้ไข (หรือตรวจสอบ) symlink คุณสามารถใช้ห้องสมุดทุบตีแพลตฟอร์มอิสระ 'realpath-lib' โดยค่าเริ่มต้นจะจำลอง readlink และจะทำงานบน Mac หรือ Unix สามารถพบได้ในGithubหรือBitbucketและฟรี

แต่ดูเหมือนว่าคุณต้องการทำ python2 (แทนที่จะเป็น. /python2) จากไดเรกทอรีท้องถิ่น (ที่ใช้งาน) ของคุณ อาจเป็นไปได้ที่จะทำเช่นนี้ด้วยนามแฝงใน. bashrc ของคุณหรือคุณจะต้องเพิ่มไดเรกทอรีทำงาน (ที่มี symlink ของคุณ) ลงในตัวแปรสภาพแวดล้อม PATH ของคุณ ซึ่งสามารถทำได้สำหรับเซสชันปัจจุบันเท่านั้นหรือภายในไฟล์. bashrc สำหรับเซสชันในอนาคต นี่อาจเป็นคำตอบสำหรับผู้ใช้ที่เฉพาะเจาะจง

ตัวเลือกอื่นที่จะใช้งานได้สำหรับผู้ใช้ทั้งหมดคือการสร้าง python2 symlink ไปยัง / usr / bin / python ในไดเรกทอรีอื่นบนพา ธ พูดใน / usr / local / bin บางทีสิ่งที่ชอบ:

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

จากนั้นผู้ใช้หรือสคริปต์ควรค้นหาคำสั่ง python หรือ python2 แน่นอนว่าตัวเลือกนี้ต้องใช้สิทธิ์ผู้ดูแลระบบ (รูท) ในการติดตั้ง


ในที่สุดฉันก็ยอมแพ้ มีหลายสถานที่ที่สมมติว่า 'python2' ในรหัสและไม่ใช่ทุกโซลูชันที่แปลเป็นภาษาท้องถิ่นครอบคลุมความเป็นไปได้ทั้งหมด นี่คือค้อนขนาดใหญ่ที่เหมาะสมที่สุดสำหรับเล็บนี้
เอเวอรี่ชาน

@ ทุกครั้งคุณลองใช้โซลูชันของฉันหรือไม่ มีปัญหาหรือไม่? มันจะไม่ได้ต้องให้คุณสามารถเพิ่มpython2ไป/usr/bin( แต่ผมดูเพิ่มเป็นการปรับปรุงจะซื่อสัตย์)
alexis

อาจเป็นไปได้ที่จะทำเช่นนี้ด้วยนามแฝง (... )เป็นไปไม่ได้เนื่องจากนามแฝงมีอิทธิพลกับบรรทัดคำสั่งเท่านั้นและไม่ใช่สคริปต์ ดูวิธีเปลี่ยน Python เวอร์ชั่นเริ่มต้นใน Debian 7.5 ได้อย่างไร
Piotr Dobrogost

นี่ไม่ใช่คำตอบที่ถูกต้องอย่างน้อยก็ไม่ได้แก้ปัญหาที่ทำให้ผู้โพสต์ถามคำถาม
smaudet

16

ฉันเชื่อว่าคุณกำลังใช้งานระบบของ Apple เพื่อจัดการและสลับไปมาระหว่างโปรแกรมรุ่นเดียวกันหลายรุ่น คุณสามารถทำสิ่งที่คุณต้องการได้อย่างหรูหรา แต่ไร้ปัญหาด้วยสคริปต์ต่อไปนี้ชื่อpython2:

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

ทำให้สามารถเรียกใช้งานได้ ( chmod +x python2) และคุณอยู่ในธุรกิจ

คำอธิบายของปัญหา:

เมื่อคุณเรียกใช้/usr/bin/pythonมันจะค้นหาและดำเนินการpython2.7 ในไดเรกทอรีเดียวกัน ลิงก์สัญลักษณ์ของคุณล้มเหลวเนื่องจากระบบติดตาม symlink ไป/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/pythonsymlink โปรดระบุให้ชัดเจนยิ่งขึ้น
Piotr Dobrogost

นั่นเป็นสิ่งที่เลวร้ายอย่างน่าประหลาดใจ ..
ลัส

มีอะไรเลวร้ายอย่างน่าอัศจรรย์?
alexis

ใช่สิ่งที่ไม่ได้กล่าวถึงอย่างชัดเจนคือฉันคิดว่า / usr / bin / python ไม่ใช่ python จริง ๆ แล้วมันแค่มองหางูหลาม MacOS ที่ติดตั้ง (python2.7 ซึ่งเชื่อมโยงกับโฟลเดอร์เฟรมเวิร์ก) ฉันสงสัยว่า @ นิโคลัสกำลังบอกว่ารุ่นงูหลามปลอมนั้นแย่มาก - มันค่อนข้างแฮ็คและฉันหวังว่า 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} " สคริปต์ตัวตัดคำหมายถึงไฟล์ไพ ธ อนทุกตัวที่ฉันจะใช้ ต้องสร้างไฟล์เพิ่มเติมลิงก์ wrapperไปยังไฟล์ python ที่เรียกใช้งานได้สร้างสิ่งที่ฉันต้องทำ
Avery Chan

@ ทุกคนฉันไม่คิดอย่างนั้น สคริปต์ตัวตัดคำสามารถระบุฟังก์ชันเชลล์หรือนามแฝงที่มีชื่อเดียวกันกับไฟล์เรียกทำงานได้ นอกจากนี้ยังสามารถ--bind mountปฏิบัติการในไดเรกทอรีปัจจุบันหรือ (ลินุกซ์เท่านั้นฉันเดา) แม้chrootตามความจำเป็น แต่ ใช้$PATHงานได้กับไดเรกทอรีใด ๆและไม่เจาะจง สิ่งนี้เป็นอันตรายสำหรับผู้ใช้ของคุณ ไม่ว่าในกรณีใดฉันแสดงให้เห็นอย่างชัดเจนถึงวิธีการดังกล่าวข้างต้น มันไม่เป็นไปตามความต้องการของคุณ?
mikeserv

0

Re @alexis ตอบกลับเวอร์ชั่นของไพ ธ อน/usr/binไม่ใช่ไพ ธ อนจริง

สิ่งนี้ควรปรากฏชัดในสามวิธี:

  1. ข้อผิดพลาดที่เราได้รับไม่ใช่ข้อผิดพลาดที่โดยทั่วไปแล้ว ลักษณะการทำงานของหลามไม่ได้มองหางูหลามตัวอื่น แต่อย่างใดเพื่อใช้งานสคริปต์งูหลาม

  2. หากคุณคำนวณ shasum ของ/usr/bin/pythonและ python2.7 จริงซึ่งรัน:

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

พวกเขาแตกต่างอย่างสิ้นเชิง นอกจากนี้ขนาดไฟล์ต่างกันประมาณ 20k ไบต์:

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

เมื่อเทียบกับ

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

นี่คือสาเหตุที่ผลงานต่อไปนี้ (คำตอบของ courtesy @ 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
ฉันอัปเดตตัวอย่างแล้ว การพิสูจน์ตัวตนแบบไบนารีนั้นเป็นปัญหาที่ยากซึ่งเป็นเหตุผลว่าทำไมฉันไม่ได้กล่าวถึงที่นี่อย่างสมบูรณ์ (ขนาดอาจแตกต่างกันอย่างถูกต้องระหว่างรุ่นพฤติกรรมสามารถเปลี่ยนแปลงได้ - หลักฐานที่ฉันโพสต์ในคำตอบที่อัปเดตของฉันคือ การติดตั้ง vanilla python นั้นควรจะทำงานฉันไม่คิดว่าคำตอบเกี่ยวกับวิศวกรรมย้อนกลับไพ ธ อนไพ ธ อนจะเหมาะสมหรือมีประโยชน์จริงๆที่นี่) แต่ฉันเข้าใจประเด็นของคุณ
smaudet
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.