Câu hỏi Đã xảy ra lỗi với `.profile` của tôi


Gần đây tôi đã cài đặt một vài phần mềm và cần thêm bin/ thư mục của tôi PATH. Không có gì bất thường cho đến nay. Nhưng tôi quyết định thông minh về nó và viết lại một phần của .profile vì vậy tôi không phải sao chép / dán cùng một vài dòng mã liên tục. Đây là ý tưởng của tôi:

# Create an array with directories to be added to PATH
declare -a addpath=("$HOME/bin" "$HOME/.cabal/bin" "/opt/vert.x/current/bin")

# Add directories recursively
for dir in "${addpath[@]}"; do
if [ -d "$dir" ]; then
    PATH="$dir:$PATH"
fi
done

Tôi nghĩ rằng điều này đã làm việc tốt .. cho đến khi tôi khởi động lại máy tính của tôi và đã bị khóa trong phiên của tôi khi cố gắng đăng nhập. Tôi mất một thời gian để tìm ra rằng đó thực sự là vì tôi .profile; một khi tôi nhận xét những dòng đó, tôi đã có thể đăng nhập vào phiên của mình mà không bị trả lại.

Câu hỏi của tôi là; tôi đã làm gì sai với những dòng này? Có lỗi cú pháp không? Có cách nào khác tốt hơn để làm điều đó không? Chuyện gì đã xảy ra?


4
2017-08-19 23:55


gốc




Các câu trả lời:


bên trong thiết lập mặc định trên Ubuntu 12.04, các .profile tệp được tải bởi /usr/sbin/lightdm-session. Đây là kịch bản lệnh shell, được thực thi bởi /bin/sh.

Trên Ubuntu, /bin/sh Là dấu gạch ngang. Bạn đã sử dụng các tính năng của bash dấu gạch ngang đó không hỗ trợ. Dash và Bash đều có các tính năng cốt lõi giống nhau, nhưng dấu gạch ngang bám vào các tính năng cốt lõi này để nhanh chóng và nhỏ trong khi bash thêm rất nhiều tính năng với chi phí đòi hỏi nhiều tài nguyên hơn. Người ta thường sử dụng dấu gạch ngang cho các tập lệnh không cần các tính năng bổ sung và bash để sử dụng tương tác (mặc dù zsh  có rất nhiều tính năng đẹp hơn).

Dấu gạch ngang không có mảng hoặc cũng không declare được xây dựng trong, do đó, nó ném bom trên dòng đó. Bạn có thể đặt danh sách đường dẫn nội tuyến:

for dir in "$HOME/bin" "$HOME/.cabal/bin" "/opt/vert.x/current/bin"; do
  if [ -d "$dir" ]; then
    PATH="$dir:$PATH"
  fi
done

Xem giữ các bản sao trong số $ PATH trên nguồn nếu bạn muốn chắc chắn không kết thúc với các mục trùng lặp.


Thay vì thêm các thư mục mới vào PATH cho mỗi chương trình bạn cài đặt, bạn có thể muốn thiết lập các liên kết tượng trưng trong một thư mục hiện có thay thế. Dành cho ~/.cabal/bin, bạn sẽ muốn có nó trong con đường của bạn bởi vì thực thi sẽ đến và đi; Tuy nhiên, tôi sẽ đặt nó ở cuối PATH, để tránh xung đột tiềm ẩn với các chương trình hiện có trên hệ thống của bạn. ~/bin đã có trong PATH của bạn trên Ubuntu. Đối với các chương trình bạn cài đặt thủ công như vert.x, xếp hàng hoặc là xstow là tốt đẹp để quản lý các liên kết tượng trưng. Xem Theo dõi các chương trình cho một giới thiệu để xếp.


6
2017-08-20 07:40



Xin lỗi vì đã đến lúc tôi quay lại với bạn. Cảm ơn bạn vì thế nhiều cho câu trả lời chi tiết của bạn, tôi chắc chắn đã học được điều gì đó ngay tại đây! - Sheljohn


Tôi nghĩ rằng, trong trường hợp của bạn, thực hành tốt nhất để làm cho các tệp nhị phân của bạn có sẵn như các lệnh là liên kết những gì bạn cần đến / usr / bin. Lộn xộn với $ PATH không bao giờ là một điều tốt để làm.

Bạn có thể sử dụng 'cp' để tạo các liên kết tượng trưng, ​​đệ quy, như sau:

cp -rs $HOME/bin/* /usr/bin #This will link all non hidden files
cp -rs $HOME/bin/.[^.]* /usr/bin # This will link all the hidden files

Chỉ cần điều chỉnh điều này cho kịch bản của bạn, sử dụng cùng một logic của mã hiện tại của bạn.

EDIT: bạn chỉ có thể sử dụng dòng đầu tiên của mã ở trên nếu bạn đặt dotglob thành thật trên bash. Như thế này:

shopt -s dotglob #This will make Bash include filenames beginning with a '.' in the results of filename expansion
cp -rs $HOME/bin/* /usr/bin #Now, this will link ALL files in that directory to the destination

EDIT 2: Như bạn có thể đọc trong các ý kiến ​​dưới đây, là thích hợp hơn mà bạn sử dụng / usr / local / bin thay vì / usr / bin. Đọc các bình luận để hiểu tại sao.


-2
2017-08-20 00:59



Nó hoàn toàn ngược lại. Bạn không bao giờ nên lộn xộn với /usr/bin, hãy để người quản lý gói quản lý nó. Bạn có thể thêm chương trình vào /usr/local/bin, nhưng là liên kết tượng trưng, ​​không phải là bản sao. - Gilles
Nếu bạn đọc mã của tôi, bạn sẽ thấy rằng tôi không sử dụng bản sao. 'cp' có thể viết các liên kết tượng trưng thay vì sao chép. Điều này đơn giản hơn làm cho tất cả các liên kết tượng trưng với 'ln'. Những gì bạn nói về / usr / bin có thể là một nửa thực sự ở đây trên Ubuntu (mà thực sự sử dụng một trình quản lý gói) nhưng không phải là một sự thật toàn cầu, hãy nhớ điều này. Tái bút: KHÔNG BAO GIỜ là một từ lạ trên thế giới Linux. Bạn có thể, rõ ràng, làm điều đó (và tất cả sẽ làm việc trên hầu hết các trường hợp). Sự khác biệt ở đây là / usr / bin lưu trữ phần mềm được quản lý phân phối và / usr / local / bin lưu trữ phần mềm khác. Nhưng đây là một quy ước, không phải là một vấn đề kỹ thuật. - Alexandre Teles
Oh, phải, tôi đã bỏ lỡ -s. Nhưng phần chính của sự phản đối của tôi vẫn đứng lên: đừng làm phiền /usr/bin. Đó là sự thật trên Ubuntu và khá nhiều unix khác. Chắc chắn, nó không phải là một định luật vật lý. Đó là một quy ước, như lái xe ở một phía nào đó của con đường. Một số quy ước là quan trọng. - Gilles
@AlexandreTeles Cảm ơn rất nhiều vì câu trả lời của bạn. Tôi biết được downvoted có thể rất bực bội; bạn đang có ý định giúp đỡ, và bạn bị "trừng phạt". Tôi thực sự xin lỗi về điều đó (tôi đã không downvote bản thân mình, ngay cả khi tôi nên). Sự thật là, bạn thực sự sai, nhưng tôi khuyến khích bạn đọc hai bài viết sau để tìm hiểu lý do: wiki.debian.org/FilesystemHierarchyStandard và sau đó unix.stackexchange.com/questions/11544/…. Thật sự của bạn :) - Sheljohn