Làm cách nào để tôi có được 'realpath' để tìm liên kết tượng trưng của mình?


13

Tôi đang sử dụng MacOSX bash. Tôi có liên kết tượng trưng, ​​được tạo như thế này:

ln -s /usr/bin/python python2 

Tôi có một gói sử dụng python2 và tôi muốn tạo một liên kết biểu tượng trong thư mục làm việc hiện tại của tôi /usr/bin/pythonthực sự là python2. Khi tôi thực hiện python2từ dòng lệnh, tôi gặp lỗi này:

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

Nhưng gọi nó như thế này ./python2giải quyết đường dẫn chính xác. Của tôi PATH.trong đó. Trong thực tế, tôi đã sửa đổi nó, để thử nghiệm, chỉ có .trong đó.

Làm thế nào để tôi giải quyết điều này? Cảm ơn!


Bối cảnh

Một số giải pháp được đề xuất dưới đây sẽ không hiệu quả với tôi. Tôi đã cố gắng chắt lọc câu hỏi của mình một cách tập trung và ngắn gọn nhất có thể để mọi người không bị chìm trong một biển văn bản, nhưng rõ ràng tôi cần cung cấp thêm thông tin cơ bản.

Tôi đang cố gắng phát triển trên một gói mà tôi đã nhân bản từ git. Gói ban đầu git-multimail, được / được phát triển trên một số biến thể của Linux (tôi đoán là Ubuntu). Tôi đã cố gắng sửa đổi nó để có thể sử dụng nó và bộ thử nghiệm của nó trên MacOSX với ít sửa đổi nhất có thể. Đây là lý do tại sao một số giải pháp được đề xuất không lý tưởng:

  1. Là root, tạo python2symlink trong / usr / bin /. Tôi đang tìm kiếm một giải pháp sẽ không yêu cầu điều này. Đây là một lựa chọn rõ ràng lúc đầu, nhưng tôi muốn một giải pháp sửa đổi hệ thống máy chủ ít nhất có thể. Đây là lý do tại sao tôi muốn tạo một liên kết tượng trưng tạm thời trong thư mục làm việc hiện tại, thêm CWD (tức là .) vào đường dẫn của tôi và sau đó hủy điều này khi kết thúc (tức là liên kết tượng trưng).

  2. Tạo một tập lệnh bao bọc để gọi tập lệnh python với python hiện có. Vấn đề với điều này là phần lớn bộ kiểm thử sử dụng script_files thực tế làm tệp thực thi, tùy thuộc vào shebang để tìm môi trường thực thi chính xác. Điều này có nghĩa là chỉnh sửa bộ kiểm tra đáng kể. Trong ngữ cảnh này, (xem bên dưới để biết một đoạn của khung kiểm tra), tôi sẽ phải thêm một trình bao bọc cho mỗi .pytệp; hơn nữa người dùng / nhà phát triển sẽ phải nhận thức được các quy tắc khác nhau khi sử dụng gói tùy thuộc vào hệ thống họ đang sử dụng (tức là trên MacOSX đảm bảo bạn không sử dụng các tệp python mà không gọi chúng qua trình bao bọc hoặc gọi rõ ràng /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. Thay đổi tất cả các python2tham chiếu đến python. README gợi ý điều này, nhưng điều này thực sự khiến việc kiểm soát phiên bản trở nên vô dụng vì hệ thống coi sự thay đổi là phiên bản mới, trong khi thực tế nó không phải là (về mặt ngữ nghĩa).

Tôi đã sử dụng (3) nhưng tôi đang cố gắng tìm một giải pháp tốt hơn. Tôi sẵn sàng chấp nhận rằng đây chỉ là cách mọi thứ diễn ra (nghĩa là không có cách nào phù hợp để chỉ ra 'python2' /usr/bin/pythonlà di động và không phô trương mà không có nhiều thay đổi đối với bộ thử nghiệm và khung thực tế).


1
Chào! Chỉ cầnln -s /usr/bin/python /usr/bin/python2
enedil

Quả thực tôi phát triển git-multimail trên Linux. Nhưng tôi hoan nghênh các bản vá và trình kiểm tra để làm cho nó hoạt động trên OS X. BTW, vấn đề "python2" của bạn đã được giải quyết ngay bây giờ, vì git-multimail chấp nhận cả python2 và python3 :-).
Matthieu Moy

Câu hỏi mở rộng vẫn còn thiếu một chi tiết quan trọng: dòng shebang trong các tập lệnh thực thi trông như thế nào? Đối với git-multimail.pynó là #!/usr/bin/env python2, vì vậy có một cách (tương đối) đơn giản để làm điều này.
alexis

Nhận xét của @ enedil không hoạt động, tuy nhiên ln -s /usr/bin/python2.7 /usr/local/bin/python2đã làm
Phylliida

Câu trả lời:


3

Nếu bạn cần giải quyết (hoặc điều tra) một liên kết tượng trưng, ​​bạn có thể sử dụng thư viện bash độc lập nền tảng 'realpath-lib'. Theo mặc định, nó mô phỏng đường dẫn đọc và sẽ hoạt động trên Mac hoặc Unix. Nó có thể được tìm thấy trên Github hoặc Bitbucket và nó miễn phí.

Nhưng có vẻ như bạn chỉ muốn làm python2 (chứ không phải ./python2) từ thư mục (làm việc) cục bộ của bạn. Có thể thực hiện điều này với một bí danh trong .bashrc hoặc nếu không, bạn sẽ cần thêm thư mục làm việc (có chứa liên kết tượng trưng của bạn) vào biến môi trường PATH của bạn. Điều này cũng có thể được thực hiện cho phiên hiện tại hoặc trong tệp .bashrc cho các phiên trong tương lai. Đây có thể là một giải pháp cho chỉ một người dùng cụ thể.

Một tùy chọn khác có thể hoạt động cho tất cả người dùng là tạo symlink python2 tới / usr / bin / python trong một thư mục khác trên đường dẫn, nói trong / usr / local / bin. Có lẽ một cái gì đó như:

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

Sau đó, bất kỳ người dùng hoặc tập lệnh nào cũng nên tìm các lệnh python hoặc python2. Tất nhiên tùy chọn này yêu cầu quyền quản trị (root) để cài đặt.


Cuối cùng tôi đã bỏ cuộc. Có quá nhiều nơi giả sử 'python2' trong mã và không phải mọi giải pháp địa phương đều bao gồm tất cả các khả năng. Đây là búa tạ thích hợp nhất cho móng này.
Avery Chan

@Avery, bạn đã thử giải pháp của tôi? Có vấn đề gì à? Nó sẽ không yêu cầu bạn thêm python2vào /usr/bin(mặc dù tôi xem việc thêm nó như một sự cải tiến, phải trung thực).
alexis

Có thể làm điều này với một bí danh (...) Không thể vì bí danh chỉ ảnh hưởng đến dòng lệnh và không phải tập lệnh. Xem Cách thay đổi phiên bản mặc định của Python trong Debian 7.5?
Piotr Dobrogost

15

Tôi tin rằng bạn đang chạy hệ thống của Apple để quản lý và chuyển đổi giữa nhiều phiên bản của cùng một chương trình. Bạn có thể thực hiện những gì bạn muốn, ít thanh lịch nhưng không có vấn đề, với tập lệnh sau có tên python2:

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

Làm cho nó có thể thực thi được ( chmod +x python2) và bạn đang kinh doanh.

Giải thích về vấn đề:

Khi bạn chạy /usr/bin/python, nó tìm và thực thi python2.7 trong cùng một thư mục. Liên kết tượng trưng của bạn không thành công vì hệ thống theo liên kết tượng trưng đến /usr/bin, sau đó tìm và không tìm thấy python2 ở đó. Bạn có thể tiến thêm một bước bằng cách sử dụng "liên kết cứng" thay vì liên kết tượng trưng:

rm python2
ln /usr/bin/python python2

Bây giờ không có liên kết tượng trưng để theo dõi, chỉ có hai tên tệp cho cùng một tệp (inode). Nhưng bây giờ tôi thất bại với thông báo sau:

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

Lưu ý python22.7: Khung đang thêm 2.7vào tên bạn đã tạo! Thay vì cố gắng làm sáng tỏ điều này và thiết lập một rừng các liên kết phù hợp với mong đợi của nó, tôi khuyên bạn nên tránh xa khung quản lý phiên bản và sử dụng giải pháp được đề xuất ở trên.

Tái bút Có thể có một giải pháp tốt hơn: Nếu bạn sẽ giải thích những gì bạn cần làm để bắt đầu (tại sao bạn cần cung cấp python2như một bí danh cho python), ai đó có thể có thể giúp bạn làm điều đó theo một cách khác. Điều này được gọi là "vấn đề XY" trong biệt ngữ stackexchange ...


Khi bạn chạy /usr/bin/python, nó tìm và thực thi python2.7 trong cùng thư mục. Đây là tuyên bố rất khó hiểu. Nếu bạn mô tả trường hợp /usr/bin/pythonlà một symlink thì hãy cụ thể hơn.
Piotr Dobrogost

điều đó thật tồi tệ ..
nicolas

Điều gì là xấu đáng kinh ngạc?
alexis

2

Thử:

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

Không biết tại sao bạn lại bị downvote, đây là giải pháp duy nhất hiệu quả với tôi
xApple

1

Bạn có thể sử dụng lệnh Unix readlinkđể tìm ra đường dẫn vật lý liên kết.

Ví dụ

Nói rằng tôi có liên kết sau:

$ 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. Để tìm giá trị, một liên kết tượng trưng chỉ đến

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

    LƯU Ý: Kết quả trên có thể là một liên kết khác. Để giải quyết vấn đề này, xem # 2 bên dưới.

  2. Để tìm ra đường dẫn tuyệt đối của giá trị, một liên kết tượng trưng chỉ đến

    $ readlink -f /usr/bin/etags
    /usr/bin/ctags

0

Tôi không hiểu - làm thế nào mà bạn tin rằng một bọc liên kết là ok, nhưng không phải là một tập lệnh trình bao bọc ? Hoặc là một trong những chỉ đơn thuần là mức độ gián tiếp. Và bạn vẫn sẽ phải hướng dẫn người dùng của mình chỉ gọi nó từ một thư mục nhất định chứ?

Trong mọi trường hợp, bạn có thể nhận được thư mục làm việc hiện tại trong $PATH khóa học:

 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

Xin vui lòng . ra khỏi bạn $PATH. Đó là một ý tưởng khủng khiếp.


Tại sao .trong $ PATH của tôi là một ý tưởng tồi? Nếu tôi đặt nó ở cuối, sau đó là nơi cuối cùng mà sẽ được xem xét là thư mục làm việc hiện tại của tôi (tức là 'PATH = "$ {PATH}: $ {PWD}". Một wrapper kịch bản phương tiện mà cho mỗi file python tôi sẽ phải tạo một tập tin bổ sung. Một liên kết trình bao bọc để thực thi python chỉ tạo ra một việc cho tôi làm
Avery Chan

@AveryChan Tôi không nghĩ vậy. Một tập lệnh bao bọc có thể nguồn một hàm shell hoặc bí danh có cùng tên với tệp thực thi. Nó cũng có thể --bind mountthực thi trong thư mục hiện tại hoặc (chỉ linux, tôi đoán) ngay cả chrootkhi cần thiết. Nhưng . trong $PATHcông việc cho bất kỳ thư mục và không cụ thể. Điều này là nguy hiểm cho người dùng của bạn. Trong mọi trường hợp, tôi đã trình bày rất rõ cách thực hiện ở trên. Nó không đáp ứng yêu cầu của bạn?
mikeerv
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.