Tìm hiểu những tập lệnh nào đang được chạy bởi bash khi khởi động


15

Sau khi bắt đầu một bash terminal, tôi nhận thấy rằng biến PATH chứa các mục trùng lặp. Thiết bị đầu cuối của tôi bắt đầu một vỏ đăng nhập , do đó ~/.bash_profilecó nguồn gốc, theo sau ~/.profile~/.bashrc. Chỉ trong ~/.profiletôi mới tạo các mục đường dẫn được nhân đôi.

Để được mô tả, đây là thứ tự các tệp NÊN có nguồn gốc đang được lấy nguồn:

Sourced /etc/profile
Sourced /etc/bash.bashrc
Sourced .bash_profile
Sourced .profile
Sourced .bashrc

Trước khi bất kỳ ai đánh dấu đây là một bản sao của "biến PATH chứa các bản sao", hãy tiếp tục đọc.

Lúc đầu, tôi nghĩ rằng điều này phải làm với ~/.profilenguồn gốc hai lần, vì vậy tôi đã ghi tệp vào tệp nhật ký bất cứ khi nào nó có nguồn gốc, và đáng ngạc nhiên là nó chỉ đăng nhập một mục, cho tôi biết rằng nó chỉ có nguồn gốc một lần. Đáng ngạc nhiên hơn nữa là khi tôi nhận xét các mục trong đó ~/.profile, các mục vẫn xuất hiện trong PATHbiến. Điều này đã đưa tôi đến ba kết luận, một trong số đó nhanh chóng bị loại trừ:

  1. Bash bỏ qua các bình luận bash hợp lệ và vẫn thực thi mã nhận xét
  2. Có một đoạn script đọc ~/.profilevà bỏ qua bất kỳ mã nào in ra một đầu ra (ví dụ tệp nhật ký)
  3. Có một bản sao khác của tôi ~/.profileđang được cung cấp ở nơi khác

Điều đầu tiên, tôi nhanh chóng kết luận không phải là trường hợp do một số thử nghiệm nhanh. Các tùy chọn thứ hai và thứ ba là nơi tôi cần giúp đỡ.

Làm cách nào để thu thập nhật ký các tập lệnh được thực thi khi thiết bị đầu cuối của tôi khởi động? Tôi đã sử dụng echotrong các tệp mà tôi đã kiểm tra để biết liệu chúng có nguồn gốc từ bash hay không, nhưng tôi cần tìm một phương thức kết luận theo dõi việc thực thi đến điểm khi thiết bị đầu cuối sẵn sàng để tôi bắt đầu nhập vào nó.

Nếu những điều trên là không thể, thì bất cứ ai cũng có thể đề nghị nơi nào khác tôi có thể xem để xem tập lệnh nào đang được chạy .


Tài liệu tham khảo trong tương lai

Đây là tập lệnh mà tôi hiện đang sử dụng để thêm vào đường dẫn của mình:

function add_to_path() {
    for path in ${2//:/ }; do
        if ! [[ "${!1}" =~ "${path%/}" ]]; then # ignore last /
            new_path="$path:${!1#:}"
            export "$1"="${new_path%:}" # remove trailing :
        fi
    done
}

Tôi sử dụng nó như thế này:

add_to_path 'PATH' "/some/path/bin"

Kịch bản kiểm tra nếu đường dẫn đã tồn tại trong biến trước khi thêm nó.

Đối với người dùng zsh, bạn có thể sử dụng tương đương này:

function add_to_path() {
    for p in ${(s.:.)2}; do
        if [[ ! "${(P)1}" =~ "${p%/}" ]]; then
            new_path="$p:${(P)1#:}"
            export "$1"="${new_path%:}"
        fi
    done
}

Chỉnh sửa 28/8/2018

Một điều nữa tôi thấy tôi có thể làm với kịch bản này là sửa lỗi đường dẫn. Vì vậy, khi bắt đầu .bashrctập tin của tôi , tôi làm một cái gì đó như thế này:

_temp_path="$PATH"
PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin'
add_to_path 'PATH' "$_temp_path"
unset _temp_path

Nó là tùy thuộc vào bạn những gì PATHnên bắt đầu với. Kiểm tra PATHtrước để quyết định.


Bash chỉ đọc từ ~/.profile nếu ~/.bash_profilekhông tồn tại ...
jasonwryan

@jasonwryan, tôi lấy nguồn ~/.profile~/.bashrctừ~/.bash_profile
smac89

Câu trả lời:


30

Nếu hệ thống của bạn có stracethì bạn có thể liệt kê các tệp được mở bởi trình bao, ví dụ như sử dụng

echo exit | strace bash -li |& grep '^open'

( -licó nghĩa là vỏ đăng nhập tương tác; chỉ sử dụng -icho vỏ không đăng nhập tương tác.)

Điều này sẽ hiển thị một danh sách các tập tin mà shell đã mở hoặc cố gắng mở. Trên hệ thống của tôi, chúng như sau:

  1. /etc/profile
  2. /etc/profile.d/*(nhiều kịch bản khác nhau /etc/profile.d/)
  3. /home/<username>/.bash_profile (điều này không thành công, tôi không có tập tin như vậy)
  4. /home/<username>/.bash_login (điều này không thành công, tôi không có tập tin như vậy)
  5. /home/<username>/.profile
  6. /home/<username>/.bashrc
  7. /home/<username>/.bash_history (lịch sử của các dòng lệnh; đây không phải là một tập lệnh)
  8. /usr/share/bash-completion/bash_completion
  9. /etc/bash_completion.d/* (các tập lệnh khác nhau cung cấp chức năng tự động hoàn thành)
  10. /etc/inputrc (xác định các ràng buộc chính; đây không phải là một tập lệnh)

Sử dụng man straceđể biết thêm thông tin.


Cảm ơn cho đầu vào của bạn, nhưng tôi nghĩ rằng có một cái gì đó sai nghiêm trọng với bash của tôi. Chạy echo $0trong thiết bị đầu cuối cho -bashhơn là mong đợi bash. Bạn có bất cứ đề nghị khác cho điều này?
smac89

3
@ smac89: Đó là bình thường cho một vỏ đăng nhập. Bash hoạt động như một vỏ đăng nhập khi ký tự đầu tiên của $0dấu gạch ngang -hoặc khi được gọi với tùy chọn -l.
AlexP

OK đó là một chút nhẹ nhõm. Tôi đã chạy lệnh bạn đã đưa ra và đầu ra trông thực sự phức tạp, nhưng dù sao tất cả các tệp được hiển thị không chứa các mục trùng lặp. Điều này khiến tôi nghĩ rằng các mục trùng lặp xảy ra khi tôi đăng nhập lần đầu vào tài khoản của mình, tức là có gì đó ban đầu tìm nguồn cung ứng trong tệp đó và nó được thực hiện lại khi tôi mở thiết bị đầu cuối? Thật ra tôi nghĩ rằng đó có thể là nó. Khi tôi đăng nhập vào tài khoản của mình, các mục nhập có nguồn gốc và một lần nữa khi tôi mở thiết bị đầu cuối, quy trình được lặp lại. Liệu âm thanh đó có thể?
smac89

Tại sao bạn không gỡ lỗi theo cách cũ, bằng cách đặt echo PATH=\""$PATH"\"ở đầu và cuối .profile.bashrc? Và tại sao bạn không làm những gì mọi người làm và thiết lập PATH đầy đủ, hoặc, nếu thêm một thư mục, được bảo vệ : echo ":$PATH:" | grep -q ":/path/to/dir:" || export PATH="$PATH:/path/to/dir"?
AlexP

4
Sử dụng sudo bash -c "echo exit|dtruss bash -li|& less|grep '^open'"trên macOS. (chỉ cần thay thế stracebằng dtruss)
Max Coplan 19/11/18
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.